mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-02 14:51:40 +00:00
synced imuse digital with scummvm imuse and related stuff
This commit is contained in:
parent
857527b278
commit
f11e24b7b1
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
|
||||
|
||||
|
||||
typedef struct Mutex *MutexRef;
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#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
|
||||
* 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
|
||||
* 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 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 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
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* 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 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
|
||||
* 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$
|
||||
@ -24,30 +24,15 @@
|
||||
#define COMMON_TIMER_H
|
||||
|
||||
#include "common/sys.h"
|
||||
#include "common/platform.h"
|
||||
#include "common/noncopyable.h"
|
||||
|
||||
#define MAX_TIMERS 3
|
||||
|
||||
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];
|
||||
namespace Common {
|
||||
|
||||
class TimerManager : NonCopyable {
|
||||
public:
|
||||
Timer();
|
||||
~Timer();
|
||||
typedef void (*TimerProc)(void *refCon);
|
||||
|
||||
virtual ~TimerManager() {}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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.
|
||||
*/
|
||||
void removeTimerProc(TimerProc proc);
|
||||
|
||||
protected:
|
||||
static int timer_handler(int t);
|
||||
int handler(int t);
|
||||
virtual void removeTimerProc(TimerProc proc) = 0;
|
||||
};
|
||||
|
||||
extern Timer *g_timer;
|
||||
} // End of namespace Common
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -198,6 +198,14 @@
|
||||
RelativePath="..\..\common\debug.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\frac.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\list.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\matrix3.cpp"
|
||||
>
|
||||
@ -214,6 +222,18 @@
|
||||
RelativePath="..\..\common\matrix4.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\mutex.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\mutex.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\noncopyable.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\platform.h"
|
||||
>
|
||||
@ -222,10 +242,6 @@
|
||||
RelativePath="..\..\common\sys.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\timer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\timer.h"
|
||||
>
|
||||
@ -781,10 +797,18 @@
|
||||
RelativePath="..\..\engine\imuse\imuse_tables.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\engine\imuse\imuse_tables.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\engine\imuse\imuse_track.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\engine\imuse\imuse_track.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="smush"
|
||||
@ -813,6 +837,14 @@
|
||||
<Filter
|
||||
Name="backend"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\engine\backend\default-timer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\engine\backend\default-timer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
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/vector3d.h"
|
||||
#include "common/mutex.h"
|
||||
|
||||
#include "engine/color.h"
|
||||
#include "engine/model.h"
|
||||
@ -33,9 +34,15 @@
|
||||
#include "engine/font.h"
|
||||
#include "engine/primitives.h"
|
||||
#include "engine/actor.h"
|
||||
#include "engine/backend/default-timer.h"
|
||||
|
||||
class Material;
|
||||
class Bitmap;
|
||||
class Timer;
|
||||
|
||||
namespace Audio {
|
||||
class Mixer;
|
||||
}
|
||||
|
||||
class Driver {
|
||||
public:
|
||||
@ -116,7 +123,7 @@ public:
|
||||
/** @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.
|
||||
@ -239,25 +246,22 @@ public:
|
||||
* @param interval the interval (in milliseconds) between invocations
|
||||
* of the callback
|
||||
*/
|
||||
virtual void setTimerCallback(TimerProc callback, int interval) = 0;
|
||||
virtual void setTimerCallback() = 0;
|
||||
|
||||
virtual void clearTimerCallback() = 0;
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @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
|
||||
* can use dummy implementations for these methods.
|
||||
*/
|
||||
//@{
|
||||
|
||||
typedef Common::MutexRef MutexRef;
|
||||
|
||||
/**
|
||||
* Create a new mutex.
|
||||
* @return the newly created mutex, or 0 if an error occured.
|
||||
@ -266,6 +270,12 @@ public:
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
virtual void lockMutex(MutexRef mutex) = 0;
|
||||
@ -329,16 +339,7 @@ protected:
|
||||
};
|
||||
|
||||
extern Driver *g_driver;
|
||||
|
||||
class StackLock {
|
||||
MutexRef _mutex;
|
||||
public:
|
||||
StackLock(MutexRef mutex) : _mutex(mutex) {
|
||||
g_driver->lockMutex(_mutex);
|
||||
}
|
||||
~StackLock() {
|
||||
g_driver->unlockMutex(_mutex);
|
||||
}
|
||||
};
|
||||
extern DefaultTimerManager *g_timer;
|
||||
extern Audio::Mixer *g_mixer;
|
||||
|
||||
#endif
|
||||
|
@ -359,11 +359,22 @@ void DriverSDL::delayMillis(uint msecs) {
|
||||
SDL_Delay(msecs);
|
||||
}
|
||||
|
||||
void DriverSDL::setTimerCallback(TimerProc callback, int timer) {
|
||||
SDL_SetTimer(timer, (SDL_TimerCallback) callback);
|
||||
static SDL_TimerID _timerID = NULL;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -382,12 +393,20 @@ void DriverSDL::deleteMutex(MutexRef mutex) {
|
||||
bool DriverSDL::setSoundCallback(SoundProc proc, void *param) {
|
||||
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));
|
||||
|
||||
desired.freq = _samplesPerSec;
|
||||
desired.format = AUDIO_S16SYS;
|
||||
desired.channels = 2;
|
||||
desired.samples = 2048;
|
||||
desired.samples = (uint16)samples;
|
||||
desired.callback = proc;
|
||||
desired.userdata = param;
|
||||
|
||||
|
@ -52,7 +52,8 @@ public:
|
||||
bool pollEvent(Event &event);
|
||||
uint32 getMillis();
|
||||
void delayMillis(uint msecs);
|
||||
void setTimerCallback(TimerProc callback, int interval);
|
||||
void setTimerCallback();
|
||||
void clearTimerCallback();
|
||||
|
||||
MutexRef createMutex();
|
||||
void lockMutex(MutexRef mutex);
|
||||
|
@ -42,7 +42,7 @@ Font::Font(const char *filename, const char *data, int /*len*/) :
|
||||
data += 32;
|
||||
|
||||
// Read character indexes - are the key/value reversed?
|
||||
_charIndex = (uint16 *)malloc(sizeof(_charIndex) * _numChars);
|
||||
_charIndex = new uint16[_numChars];
|
||||
if (!_charIndex)
|
||||
error("Could not load font %s. Out of memory\n", filename);
|
||||
for (uint i = 0; i < _numChars; ++i) {
|
||||
@ -52,7 +52,7 @@ Font::Font(const char *filename, const char *data, int /*len*/) :
|
||||
data += _numChars * 2;
|
||||
|
||||
// Read character headers
|
||||
_charHeaders = (CharHeader *)malloc(sizeof(CharHeader) * _numChars);
|
||||
_charHeaders = new CharHeader[_numChars];
|
||||
if (!_charHeaders)
|
||||
error("Could not load font %s. Out of memory\n", filename);
|
||||
for (uint i = 0; i < _numChars; ++i) {
|
||||
@ -65,7 +65,7 @@ Font::Font(const char *filename, const char *data, int /*len*/) :
|
||||
data += 16;
|
||||
}
|
||||
// Read font data
|
||||
_fontData = (byte *)malloc(_dataSize);
|
||||
_fontData = new byte[_dataSize];
|
||||
if (!_fontData)
|
||||
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() {
|
||||
free(_charIndex);
|
||||
free(_charHeaders);
|
||||
free(_fontData);
|
||||
delete[] _charIndex;
|
||||
delete[] _charHeaders;
|
||||
delete[] _fontData;
|
||||
}
|
||||
|
||||
uint16 Font::getCharIndex(unsigned char c) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "common/platform.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/timer.h"
|
||||
#include "common/mutex.h"
|
||||
|
||||
#include "engine/engine.h"
|
||||
#include "engine/savegame.h"
|
||||
@ -42,26 +43,20 @@ extern ImuseTable grimSeqMusicTable[];
|
||||
extern ImuseTable grimDemoStateMusicTable[];
|
||||
extern ImuseTable grimDemoSeqMusicTable[];
|
||||
|
||||
Imuse::Track::Track()
|
||||
: used(false), stream(NULL) {
|
||||
}
|
||||
|
||||
void Imuse::timerHandler(void *refCon) {
|
||||
Imuse *imuse = (Imuse *)refCon;
|
||||
imuse->callback();
|
||||
}
|
||||
|
||||
Imuse::Imuse(int fps) {
|
||||
_mutex = g_driver->createMutex();
|
||||
_pause = false;
|
||||
_sound = new ImuseSndMgr();
|
||||
_volVoice = 0;
|
||||
_volSfx = 0;
|
||||
_volMusic = 0;
|
||||
assert(_sound);
|
||||
_callbackFps = fps;
|
||||
resetState();
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
_track[l] = new Track;
|
||||
assert(_track[l]);
|
||||
_track[l]->trackId = l;
|
||||
_track[l]->used = false;
|
||||
strcpy(_track[l]->soundName, "");
|
||||
@ -73,13 +68,12 @@ Imuse::Imuse(int fps) {
|
||||
}
|
||||
|
||||
Imuse::~Imuse() {
|
||||
stopAllSounds();
|
||||
g_timer->removeTimerProc(timerHandler);
|
||||
stopAllSounds();
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
delete _track[l];
|
||||
}
|
||||
delete _sound;
|
||||
g_driver->deleteMutex(_mutex);
|
||||
}
|
||||
|
||||
void Imuse::resetState() {
|
||||
@ -89,19 +83,18 @@ void Imuse::resetState() {
|
||||
}
|
||||
|
||||
void Imuse::restoreState(SaveGame *savedState) {
|
||||
StackLock lock(_mutex);
|
||||
Common::StackLock lock(_mutex);
|
||||
printf("Imuse::restoreState() started.\n");
|
||||
|
||||
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(&_curMusicSeq, sizeof(int32));
|
||||
savedState->read(_attributes, sizeof(int32) * 185);
|
||||
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
memset(track, 0, sizeof(Track));
|
||||
track->trackId = l;
|
||||
savedState->read(&track->pan, sizeof(int32));
|
||||
savedState->read(&track->panFadeDest, 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->used, 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->regionOffset, sizeof(int32));
|
||||
savedState->read(&track->dataOffset, sizeof(int32));
|
||||
savedState->read(&track->curRegion, sizeof(int32));
|
||||
savedState->read(&track->curHookId, 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->mixerVol, sizeof(int32));
|
||||
savedState->read(&track->mixerPan, sizeof(int32));
|
||||
|
||||
if (!track->used)
|
||||
continue;
|
||||
|
||||
track->readyToRemove = false;
|
||||
if (track->toBeRemoved) {
|
||||
track->stream = NULL;
|
||||
if (track->toBeRemoved || track->curRegion == -1) {
|
||||
track->used = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
track->soundHandle = _sound->openSound(track->soundName, track->volGroupId);
|
||||
assert(track->soundHandle);
|
||||
track->soundDesc = _sound->openSound(track->soundName, track->volGroupId);
|
||||
if (!track->soundDesc) {
|
||||
warning("Imuse::restoreState: Can't open sound so will not be resumed");
|
||||
track->used = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
int32 streamBufferSize = track->iteration;
|
||||
int freq = _sound->getFreq(track->soundHandle);
|
||||
int channels = _sound->getChannels(track->soundDesc);
|
||||
int freq = _sound->getFreq(track->soundDesc);
|
||||
track->mixerFlags = kFlag16Bits;
|
||||
if (channels == 2)
|
||||
track->mixerFlags |= kFlagStereo | kFlagReverseStereo;
|
||||
|
||||
track->stream = makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize);
|
||||
g_mixer->playInputStream(&track->handle, track->stream, false, -1, track->mixerVol, track->mixerPan, false);
|
||||
track->stream = Audio::makeAppendableAudioStream(freq, makeMixerFlags(track->mixerFlags));
|
||||
g_mixer->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
|
||||
g_mixer->pauseHandle(track->handle, true);
|
||||
}
|
||||
savedState->endSection();
|
||||
g_mixer->pauseAll(false);
|
||||
|
||||
printf("Imuse::restoreState() finished.\n");
|
||||
}
|
||||
|
||||
void Imuse::saveState(SaveGame *savedState) {
|
||||
StackLock lock(_mutex);
|
||||
Common::StackLock lock(_mutex);
|
||||
printf("Imuse::saveState() started.\n");
|
||||
|
||||
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(&_curMusicSeq, sizeof(int32));
|
||||
savedState->write(_attributes, sizeof(int32) * 185);
|
||||
@ -174,31 +168,43 @@ void Imuse::saveState(SaveGame *savedState) {
|
||||
savedState->write(track->soundName, 32);
|
||||
savedState->write(&track->used, 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->regionOffset, sizeof(int32));
|
||||
savedState->write(&track->dataOffset, sizeof(int32));
|
||||
savedState->write(&track->curRegion, sizeof(int32));
|
||||
savedState->write(&track->curHookId, 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->mixerVol, sizeof(int32));
|
||||
savedState->write(&track->mixerPan, sizeof(int32));
|
||||
}
|
||||
savedState->endSection();
|
||||
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() {
|
||||
StackLock lock(_mutex);
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
if (track->used && !track->readyToRemove) {
|
||||
if (track->toBeRemoved) {
|
||||
track->readyToRemove = true;
|
||||
if (track->used) {
|
||||
// Ignore tracks which are about to finish. Also, if it did finish in the meantime,
|
||||
// mark it as unused.
|
||||
if (!track->stream) {
|
||||
if (!g_mixer->isSoundHandleActive(track->handle))
|
||||
memset(track, 0, sizeof(Track));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -209,17 +215,21 @@ void Imuse::callback() {
|
||||
if (track->volFadeStep < 0) {
|
||||
if (track->vol > track->volFadeDest) {
|
||||
track->vol += track->volFadeStep;
|
||||
//warning("fade: %d", track->vol);
|
||||
if (track->vol < track->volFadeDest) {
|
||||
track->vol = track->volFadeDest;
|
||||
track->volFadeUsed = false;
|
||||
}
|
||||
if (track->vol == 0) {
|
||||
track->toBeRemoved = true;
|
||||
// Fade out complete -> remove this track
|
||||
flushTrack(track);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (track->volFadeStep > 0) {
|
||||
if (track->vol < track->volFadeDest) {
|
||||
track->vol += track->volFadeStep;
|
||||
//warning("fade: %d", track->vol);
|
||||
if (track->vol > track->volFadeDest) {
|
||||
track->vol = track->volFadeDest;
|
||||
track->volFadeUsed = false;
|
||||
@ -248,74 +258,60 @@ void Imuse::callback() {
|
||||
}
|
||||
}
|
||||
|
||||
int pan = track->pan / 1000;
|
||||
pan = (pan != 64) ? 2 * pan - 127 : 0;
|
||||
int vol = track->vol / 1000;
|
||||
assert(track->stream);
|
||||
byte *data = NULL;
|
||||
int32 result = 0;
|
||||
|
||||
if (track->volGroupId == 1)
|
||||
vol = (vol * _volVoice) / 128;
|
||||
if (track->volGroupId == 2)
|
||||
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)
|
||||
if (track->curRegion == -1) {
|
||||
switchToNextRegion(track);
|
||||
if (!track->stream) // Seems we reached the end of the stream
|
||||
continue;
|
||||
}
|
||||
|
||||
do {
|
||||
result = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &data, track->regionOffset, mixer_size);
|
||||
if (channels == 1) {
|
||||
result &= ~1;
|
||||
}
|
||||
if (channels == 2) {
|
||||
result &= ~3;
|
||||
}
|
||||
int channels = _sound->getChannels(track->soundDesc);
|
||||
int32 mixer_size = track->feedSize / _callbackFps;
|
||||
|
||||
if (result > mixer_size)
|
||||
result = mixer_size;
|
||||
if (track->stream->endOfData()) {
|
||||
mixer_size *= 2;
|
||||
}
|
||||
|
||||
if (g_mixer->isReady()) {
|
||||
g_mixer->setChannelVolume(track->handle, vol);
|
||||
g_mixer->setChannelBalance(track->handle, pan);
|
||||
track->stream->append(data, result);
|
||||
track->regionOffset += result;
|
||||
free(data);
|
||||
}
|
||||
if (channels == 1)
|
||||
mixer_size &= ~1;
|
||||
if (channels == 2)
|
||||
mixer_size &= ~3;
|
||||
|
||||
if (_sound->isEndOfRegion(track->soundHandle, track->curRegion)) {
|
||||
switchToNextRegion(track);
|
||||
if (track->toBeRemoved)
|
||||
break;
|
||||
}
|
||||
mixer_size -= result;
|
||||
assert(mixer_size >= 0);
|
||||
} while (mixer_size != 0);
|
||||
if (mixer_size == 0)
|
||||
continue;
|
||||
|
||||
do {
|
||||
result = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &data, track->regionOffset, mixer_size);
|
||||
if (channels == 1) {
|
||||
result &= ~1;
|
||||
}
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int numRegions = _sound->getNumRegions(track->soundHandle);
|
||||
int numRegions = _sound->getNumRegions(track->soundDesc);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ImuseSndMgr::SoundStruct *soundHandle = track->soundHandle;
|
||||
int jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, track->curHookId);
|
||||
ImuseSndMgr::SoundDesc *soundDesc = track->soundDesc;
|
||||
int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId);
|
||||
if (jumpId == -1)
|
||||
jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, 0);
|
||||
jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, 0);
|
||||
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);
|
||||
int sampleHookId = _sound->getJumpHookId(soundHandle, jumpId);
|
||||
int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId);
|
||||
assert(sampleHookId != -1);
|
||||
int fadeDelay = (60 * _sound->getJumpFade(soundHandle, jumpId)) / 1000;
|
||||
if (sampleHookId != 0) {
|
||||
if (track->curHookId == sampleHookId) {
|
||||
if (fadeDelay != 0) {
|
||||
Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
|
||||
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);
|
||||
int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000;
|
||||
if (fadeDelay) {
|
||||
Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
|
||||
if (fadeTrack) {
|
||||
fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);
|
||||
fadeTrack->regionOffset = 0;
|
||||
}
|
||||
track->curRegion = region;
|
||||
if (track->curHookId == 0x80) {
|
||||
track->curHookId = 0;
|
||||
fadeTrack->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;
|
||||
}
|
||||
|
@ -34,21 +34,12 @@
|
||||
|
||||
#include "engine/imuse/imuse_sndmgr.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_FADETRACKS 16
|
||||
|
||||
struct ImuseTable {
|
||||
byte opcode;
|
||||
int16 soundId;
|
||||
byte atribPos;
|
||||
byte hookId;
|
||||
int16 fadeOut60TicksDelay;
|
||||
byte volume;
|
||||
byte pan;
|
||||
char filename[32];
|
||||
};
|
||||
|
||||
class SaveGame;
|
||||
|
||||
class Imuse {
|
||||
@ -56,52 +47,11 @@ private:
|
||||
|
||||
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];
|
||||
|
||||
MutexRef _mutex;
|
||||
Common::Mutex _mutex;
|
||||
ImuseSndMgr *_sound;
|
||||
|
||||
int32 _volVoice;
|
||||
int32 _volSfx;
|
||||
int32 _volMusic;
|
||||
|
||||
bool _pause;
|
||||
|
||||
int32 _attributes[185];
|
||||
@ -111,6 +61,7 @@ private:
|
||||
const ImuseTable *_stateMusicTable;
|
||||
const ImuseTable *_seqMusicTable;
|
||||
|
||||
int32 makeMixerFlags(int32 flags);
|
||||
static void timerHandler(void *refConf);
|
||||
void callback();
|
||||
void switchToNextRegion(Track *track);
|
||||
@ -118,30 +69,27 @@ private:
|
||||
void selectVolumeGroup(const char *soundName, int volGroupId);
|
||||
|
||||
void fadeOutMusic(int fadeDelay);
|
||||
void fadeOutMusicAndStartNew(int fadeDelay, const char *filename, int hookId, int vol, int pan);
|
||||
Track *cloneToFadeOutTrack(Track *track, int fadeDelay);
|
||||
|
||||
void playMusic(const ImuseTable *table, int atribPos, bool sequence);
|
||||
|
||||
void flushTrack(Track *track);
|
||||
|
||||
public:
|
||||
Imuse(int fps);
|
||||
~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 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 restoreState(SaveGame *savedState);
|
||||
void saveState(SaveGame *savedState);
|
||||
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);
|
||||
void setPriority(const char *soundName, int priority);
|
||||
void setVolume(const char *soundName, int volume);
|
||||
@ -160,6 +108,8 @@ public:
|
||||
void flushTracks();
|
||||
bool isVoicePlaying();
|
||||
char *getCurMusicSoundName();
|
||||
int getCurMusicPan();
|
||||
int getCurMusicVol();
|
||||
bool getSoundStatus(const char *soundName);
|
||||
int32 getPosIn60HzTicks(const char *soundName);
|
||||
};
|
||||
|
@ -45,10 +45,8 @@ McmpMgr::McmpMgr() {
|
||||
McmpMgr::~McmpMgr() {
|
||||
if (_file)
|
||||
fclose(_file);
|
||||
if (_compTable)
|
||||
free(_compTable);
|
||||
if (_compInput)
|
||||
free(_compInput);
|
||||
delete[] _compTable;
|
||||
delete[] _compInput;
|
||||
}
|
||||
|
||||
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;
|
||||
_numCompItems--;
|
||||
_compTable = (CompTable *)malloc(sizeof(CompTable) * _numCompItems);
|
||||
_compTable = new CompTable[_numCompItems];
|
||||
fseek(_file, 5, SEEK_CUR);
|
||||
fread(&_compTable[0].decompSize, 1, 4, _file);
|
||||
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;
|
||||
}
|
||||
fseek(_file, sizeCodecs, SEEK_CUR);
|
||||
_compInput = (byte *)malloc(maxSize);
|
||||
_compInput = new byte[maxSize];
|
||||
fread(_compInput, 1, headerSize, _file);
|
||||
*resPtr = _compInput;
|
||||
offsetData = headerSize;
|
||||
@ -123,7 +121,7 @@ int32 McmpMgr::decompressSample(int32 offset, int32 size, byte **comp_final) {
|
||||
last_block = _numCompItems - 1;
|
||||
|
||||
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;
|
||||
|
||||
for (i = first_block; i <= last_block; i++) {
|
||||
|
@ -40,10 +40,13 @@ void Imuse::setMusicState(int stateId) {
|
||||
}
|
||||
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)
|
||||
return;
|
||||
|
||||
if (_curMusicSeq == 0) {
|
||||
if (!_curMusicSeq) {
|
||||
playMusic(&_stateMusicTable[num], num, false);
|
||||
}
|
||||
|
||||
@ -68,10 +71,13 @@ int Imuse::setMusicSequence(int seqId) {
|
||||
|
||||
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)
|
||||
return _seqMusicTable[_curMusicSeq].soundId;
|
||||
|
||||
if (num != 0) {
|
||||
if (num) {
|
||||
playMusic(&_seqMusicTable[num], 0, true);
|
||||
} else {
|
||||
playMusic(&_stateMusicTable[_curMusicState], _curMusicState, true);
|
||||
@ -85,12 +91,12 @@ int Imuse::setMusicSequence(int seqId) {
|
||||
void Imuse::playMusic(const ImuseTable *table, int atribPos, bool sequence) {
|
||||
int hookId = 0;
|
||||
|
||||
if (atribPos != 0) {
|
||||
if (table->atribPos != 0)
|
||||
if (atribPos) {
|
||||
if (table->atribPos)
|
||||
atribPos = table->atribPos;
|
||||
hookId = _attributes[atribPos];
|
||||
if (table->hookId != 0) {
|
||||
if ((hookId == 0) && (table->hookId > 1)) {
|
||||
if (table->hookId) {
|
||||
if (hookId && table->hookId > 1) {
|
||||
_attributes[atribPos] = 2;
|
||||
} else {
|
||||
_attributes[atribPos] = hookId + 1;
|
||||
@ -104,27 +110,51 @@ void Imuse::playMusic(const ImuseTable *table, int atribPos, bool sequence) {
|
||||
|
||||
if (table->opcode == 0) {
|
||||
fadeOutMusic(120);
|
||||
} else if ((table->opcode == 2) || (table->opcode == 3)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (table->opcode == 2 || table->opcode == 3) {
|
||||
if (table->filename[0] == 0) {
|
||||
fadeOutMusic(60);
|
||||
} else {
|
||||
char *soundName = getCurMusicSoundName();
|
||||
int pan;
|
||||
return;
|
||||
}
|
||||
char *soundName = getCurMusicSoundName();
|
||||
int pan;
|
||||
|
||||
if (table->pan == 0)
|
||||
pan = 64;
|
||||
else
|
||||
pan = table->pan;
|
||||
if (soundName != NULL && (table->opcode == 3) && (!sequence)
|
||||
&& (strcmp(soundName, table->filename) == 0) && (table->atribPos != 0)
|
||||
&& table->atribPos == _stateMusicTable[_curMusicState].atribPos) {
|
||||
setFadeVolume(soundName, table->volume, table->fadeOut60TicksDelay);
|
||||
setFadePan(soundName, pan, table->fadeOut60TicksDelay);
|
||||
setHookId(soundName, hookId);
|
||||
} else {
|
||||
fadeOutMusic(table->fadeOut60TicksDelay);
|
||||
startMusic(table->filename, hookId, table->volume, pan);
|
||||
}
|
||||
if (table->pan == 0)
|
||||
pan = 64;
|
||||
else
|
||||
pan = table->pan;
|
||||
if (!soundName) {
|
||||
startMusic(table->filename, hookId, 0, pan);
|
||||
setFadeVolume(table->filename, table->volume, table->fadeOut60TicksDelay);
|
||||
return;
|
||||
}
|
||||
int old_pan = getCurMusicPan();
|
||||
int old_vol = getCurMusicVol();
|
||||
if (old_pan == -1)
|
||||
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/debug.h"
|
||||
#include "common/timer.h"
|
||||
#include "common/mutex.h"
|
||||
|
||||
#include "engine/backend/driver.h"
|
||||
|
||||
@ -33,34 +34,41 @@
|
||||
#include "engine/imuse/imuse.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() {
|
||||
// flushTracks should not lock the stack since all the functions
|
||||
// that call it already do (stopAllSounds, startSound)
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
if (track->used && track->readyToRemove) {
|
||||
if (track->stream) {
|
||||
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, "");
|
||||
}
|
||||
}
|
||||
if (track->used && track->toBeRemoved && !g_mixer->isSoundHandleActive(track->handle)) {
|
||||
memset(track, 0, sizeof(Track));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Imuse::refreshScripts() {
|
||||
Common::StackLock lock(_mutex);
|
||||
bool found = false;
|
||||
|
||||
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)) {
|
||||
@ -68,52 +76,58 @@ void Imuse::refreshScripts() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && (_curMusicSeq != 0)) {
|
||||
setMusicSequence(2000);
|
||||
if (!found && _curMusicState) {
|
||||
setMusicSequence(0);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
Common::StackLock lock(_mutex);
|
||||
Track *getTrack = NULL;
|
||||
|
||||
getTrack = findTrack(soundName);
|
||||
// Warn the user if the track was not found
|
||||
if (getTrack == NULL) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (getTrack->handle.isActive()) {
|
||||
int32 pos = (5 * (getTrack->dataOffset + getTrack->regionOffset)) / (getTrack->iteration / 12);
|
||||
return pos;
|
||||
}
|
||||
return -1;
|
||||
int32 pos = (5 * (getTrack->dataOffset + getTrack->regionOffset)) / (getTrack->feedSize / 200);
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool Imuse::isVoicePlaying() {
|
||||
StackLock lock(_mutex);
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS; 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->handle.isActive()) {
|
||||
if (g_mixer->isSoundHandleActive(track->handle))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,51 +135,55 @@ bool Imuse::isVoicePlaying() {
|
||||
}
|
||||
|
||||
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 (strlen(soundName) == 0)
|
||||
return false;
|
||||
|
||||
statusTrack = findTrack(soundName);
|
||||
track = findTrack(soundName);
|
||||
// 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
|
||||
// on occassion to see if a sound has stopped yet
|
||||
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 statusTrack->handle.isActive();
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
removeTrack = findTrack(soundName);
|
||||
// Warn the user if the track was not found
|
||||
if (removeTrack == NULL) {
|
||||
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;
|
||||
}
|
||||
removeTrack->toBeRemoved = true;
|
||||
flushTrack(removeTrack);
|
||||
}
|
||||
|
||||
void Imuse::stopAllSounds() {
|
||||
for (;;) {
|
||||
bool foundNotRemoved = false;
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
if (track->used) {
|
||||
track->toBeRemoved = true;
|
||||
foundNotRemoved = true;
|
||||
Common::StackLock lock(_mutex);
|
||||
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||
printf("Imuse::stopAllSounds()\n");
|
||||
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
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() {
|
||||
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'));
|
||||
}
|
||||
|
||||
void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSize) {
|
||||
void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundDesc *sound, int &headerSize) {
|
||||
if (READ_UINT32(ptr) == MKID('RIFF')) {
|
||||
sound->region = (Region *)malloc(sizeof(Region));
|
||||
sound->jump = (Jump *)malloc(0);
|
||||
sound->region = new Region[1];
|
||||
sound->jump = new Jump[0];
|
||||
sound->numJumps = 0;
|
||||
sound->numRegions = 1;
|
||||
sound->region[0].offset = 0;
|
||||
@ -96,8 +96,8 @@ void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSiz
|
||||
sound->numRegions = 0;
|
||||
sound->numJumps = 0;
|
||||
countElements(ptr, sound->numRegions, sound->numJumps);
|
||||
sound->region = (Region *)malloc(sizeof(Region) * sound->numRegions);
|
||||
sound->jump = (Jump *)malloc(sizeof(Jump) * sound->numJumps);
|
||||
sound->region = new Region [sound->numRegions];
|
||||
sound->jump = new Jump [sound->numJumps];
|
||||
|
||||
do {
|
||||
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++) {
|
||||
if (!_sounds[l].inUse) {
|
||||
_sounds[l].inUse = true;
|
||||
@ -158,12 +158,12 @@ ImuseSndMgr::SoundStruct *ImuseSndMgr::allocSlot() {
|
||||
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;
|
||||
byte *ptr = NULL;
|
||||
int headerSize = 0;
|
||||
|
||||
SoundStruct *sound = allocSlot();
|
||||
SoundDesc *sound = allocSlot();
|
||||
if (!sound) {
|
||||
error("ImuseSndMgr::openSound() Can't alloc free sound slot");
|
||||
}
|
||||
@ -197,94 +197,94 @@ ImuseSndMgr::SoundStruct *ImuseSndMgr::openSound(const char *soundName, int volG
|
||||
return sound;
|
||||
}
|
||||
|
||||
void ImuseSndMgr::closeSound(SoundStruct *soundHandle) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
void ImuseSndMgr::closeSound(SoundDesc *sound) {
|
||||
assert(checkForProperHandle(sound));
|
||||
|
||||
if (soundHandle->mcmpMgr) {
|
||||
delete soundHandle->mcmpMgr;
|
||||
soundHandle->mcmpMgr = NULL;
|
||||
if (sound->mcmpMgr) {
|
||||
delete sound->mcmpMgr;
|
||||
sound->mcmpMgr = NULL;
|
||||
}
|
||||
|
||||
if (soundHandle->blockRes) {
|
||||
delete soundHandle->blockRes;
|
||||
soundHandle->blockRes = NULL;
|
||||
if (sound->blockRes) {
|
||||
delete sound->blockRes;
|
||||
sound->blockRes = NULL;
|
||||
}
|
||||
|
||||
if (soundHandle->region) {
|
||||
free(soundHandle->region);
|
||||
soundHandle->region = NULL;
|
||||
if (sound->region) {
|
||||
delete[] sound->region;
|
||||
sound->region = NULL;
|
||||
}
|
||||
|
||||
if (soundHandle->jump) {
|
||||
free(soundHandle->jump);
|
||||
soundHandle->jump = NULL;
|
||||
if (sound->jump) {
|
||||
delete[] sound->jump;
|
||||
sound->jump = NULL;
|
||||
}
|
||||
|
||||
memset(soundHandle, 0, sizeof(SoundStruct));
|
||||
memset(sound, 0, sizeof(SoundDesc));
|
||||
}
|
||||
|
||||
ImuseSndMgr::SoundStruct *ImuseSndMgr::cloneSound(SoundStruct *soundHandle) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
ImuseSndMgr::SoundDesc *ImuseSndMgr::cloneSound(SoundDesc *sound) {
|
||||
assert(checkForProperHandle(sound));
|
||||
|
||||
return openSound(soundHandle->name, soundHandle->volGroupId);
|
||||
return openSound(sound->name, sound->volGroupId);
|
||||
}
|
||||
|
||||
bool ImuseSndMgr::checkForProperHandle(SoundStruct *soundHandle) {
|
||||
if (!soundHandle)
|
||||
bool ImuseSndMgr::checkForProperHandle(SoundDesc *sound) {
|
||||
if (!sound)
|
||||
return false;
|
||||
|
||||
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
||||
if (soundHandle == &_sounds[l])
|
||||
if (sound == &_sounds[l])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ImuseSndMgr::getFreq(SoundStruct *soundHandle) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
return soundHandle->freq;
|
||||
int ImuseSndMgr::getFreq(SoundDesc *sound) {
|
||||
assert(checkForProperHandle(sound));
|
||||
return sound->freq;
|
||||
}
|
||||
|
||||
int ImuseSndMgr::getBits(SoundStruct *soundHandle) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
return soundHandle->bits;
|
||||
int ImuseSndMgr::getBits(SoundDesc *sound) {
|
||||
assert(checkForProperHandle(sound));
|
||||
return sound->bits;
|
||||
}
|
||||
|
||||
int ImuseSndMgr::getChannels(SoundStruct *soundHandle) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
return soundHandle->channels;
|
||||
int ImuseSndMgr::getChannels(SoundDesc *sound) {
|
||||
assert(checkForProperHandle(sound));
|
||||
return sound->channels;
|
||||
}
|
||||
|
||||
bool ImuseSndMgr::isEndOfRegion(SoundStruct *soundHandle, int region) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
assert(region >= 0 && region < soundHandle->numRegions);
|
||||
return soundHandle->endFlag;
|
||||
bool ImuseSndMgr::isEndOfRegion(SoundDesc *sound, int region) {
|
||||
assert(checkForProperHandle(sound));
|
||||
assert(region >= 0 && region < sound->numRegions);
|
||||
return sound->endFlag;
|
||||
}
|
||||
|
||||
int ImuseSndMgr::getNumRegions(SoundStruct *soundHandle) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
return soundHandle->numRegions;
|
||||
int ImuseSndMgr::getNumRegions(SoundDesc *sound) {
|
||||
assert(checkForProperHandle(sound));
|
||||
return sound->numRegions;
|
||||
}
|
||||
|
||||
int ImuseSndMgr::getNumJumps(SoundStruct *soundHandle) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
return soundHandle->numJumps;
|
||||
int ImuseSndMgr::getNumJumps(SoundDesc *sound) {
|
||||
assert(checkForProperHandle(sound));
|
||||
return sound->numJumps;
|
||||
}
|
||||
|
||||
int ImuseSndMgr::getRegionOffset(SoundStruct *soundHandle, int region) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
assert(region >= 0 && region < soundHandle->numRegions);
|
||||
return soundHandle->region[region].offset;
|
||||
int ImuseSndMgr::getRegionOffset(SoundDesc *sound, int region) {
|
||||
assert(checkForProperHandle(sound));
|
||||
assert(region >= 0 && region < sound->numRegions);
|
||||
return sound->region[region].offset;
|
||||
}
|
||||
|
||||
int ImuseSndMgr::getJumpIdByRegionAndHookId(SoundStruct *soundHandle, int region, int hookId) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
assert(region >= 0 && region < soundHandle->numRegions);
|
||||
int32 offset = soundHandle->region[region].offset;
|
||||
for (int l = 0; l < soundHandle->numJumps; l++) {
|
||||
if (offset == soundHandle->jump[l].offset) {
|
||||
if (soundHandle->jump[l].hookId == hookId)
|
||||
int ImuseSndMgr::getJumpIdByRegionAndHookId(SoundDesc *sound, int region, int hookId) {
|
||||
assert(checkForProperHandle(sound));
|
||||
assert(region >= 0 && region < sound->numRegions);
|
||||
int32 offset = sound->region[region].offset;
|
||||
for (int l = 0; l < sound->numJumps; l++) {
|
||||
if (offset == sound->jump[l].offset) {
|
||||
if (sound->jump[l].hookId == hookId)
|
||||
return l;
|
||||
}
|
||||
}
|
||||
@ -292,12 +292,12 @@ int ImuseSndMgr::getJumpIdByRegionAndHookId(SoundStruct *soundHandle, int region
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ImuseSndMgr::getRegionIdByJumpId(SoundStruct *soundHandle, int jumpId) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
assert(jumpId >= 0 && jumpId < soundHandle->numJumps);
|
||||
int32 dest = soundHandle->jump[jumpId].dest;
|
||||
for (int l = 0; l < soundHandle->numRegions; l++) {
|
||||
if (dest == soundHandle->region[l].offset) {
|
||||
int ImuseSndMgr::getRegionIdByJumpId(SoundDesc *sound, int jumpId) {
|
||||
assert(checkForProperHandle(sound));
|
||||
assert(jumpId >= 0 && jumpId < sound->numJumps);
|
||||
int32 dest = sound->jump[jumpId].dest;
|
||||
for (int l = 0; l < sound->numRegions; l++) {
|
||||
if (dest == sound->region[l].offset) {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
@ -305,38 +305,38 @@ int ImuseSndMgr::getRegionIdByJumpId(SoundStruct *soundHandle, int jumpId) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ImuseSndMgr::getJumpHookId(SoundStruct *soundHandle, int number) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
assert(number >= 0 && number < soundHandle->numJumps);
|
||||
return soundHandle->jump[number].hookId;
|
||||
int ImuseSndMgr::getJumpHookId(SoundDesc *sound, int number) {
|
||||
assert(checkForProperHandle(sound));
|
||||
assert(number >= 0 && number < sound->numJumps);
|
||||
return sound->jump[number].hookId;
|
||||
}
|
||||
|
||||
int ImuseSndMgr::getJumpFade(SoundStruct *soundHandle, int number) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
assert(number >= 0 && number < soundHandle->numJumps);
|
||||
return soundHandle->jump[number].fadeDelay;
|
||||
int ImuseSndMgr::getJumpFade(SoundDesc *sound, int number) {
|
||||
assert(checkForProperHandle(sound));
|
||||
assert(number >= 0 && number < sound->numJumps);
|
||||
return sound->jump[number].fadeDelay;
|
||||
}
|
||||
|
||||
int32 ImuseSndMgr::getDataFromRegion(SoundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size) {
|
||||
assert(checkForProperHandle(soundHandle));
|
||||
int32 ImuseSndMgr::getDataFromRegion(SoundDesc *sound, int region, byte **buf, int32 offset, int32 size) {
|
||||
assert(checkForProperHandle(sound));
|
||||
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_length = soundHandle->region[region].length;
|
||||
int32 region_offset = sound->region[region].offset;
|
||||
int32 region_length = sound->region[region].length;
|
||||
|
||||
if (offset + size > region_length) {
|
||||
size = region_length - offset;
|
||||
soundHandle->endFlag = true;
|
||||
sound->endFlag = true;
|
||||
} else {
|
||||
soundHandle->endFlag = false;
|
||||
sound->endFlag = false;
|
||||
}
|
||||
|
||||
if (soundHandle->mcmpData) {
|
||||
size = soundHandle->mcmpMgr->decompressSample(region_offset + offset, size, buf);
|
||||
if (sound->mcmpData) {
|
||||
size = sound->mcmpMgr->decompressSample(region_offset + offset, size, buf);
|
||||
} else {
|
||||
*buf = (byte *)malloc(size);
|
||||
memcpy(*buf, soundHandle->resPtr + region_offset + offset, size);
|
||||
*buf = new byte[size];
|
||||
memcpy(*buf, sound->resPtr + region_offset + offset, size);
|
||||
}
|
||||
|
||||
return size;
|
||||
|
@ -64,7 +64,7 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
struct SoundStruct {
|
||||
struct SoundDesc {
|
||||
uint16 freq; // frequency
|
||||
byte channels; // stereo or mono
|
||||
byte bits; // 8, 12, 16
|
||||
@ -77,6 +77,7 @@ public:
|
||||
char name[32];
|
||||
McmpMgr *mcmpMgr;
|
||||
Block *blockRes;
|
||||
int type;
|
||||
int volGroupId;
|
||||
byte *resPtr;
|
||||
bool mcmpData;
|
||||
@ -84,11 +85,11 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
SoundStruct _sounds[MAX_IMUSE_SOUNDS];
|
||||
SoundDesc _sounds[MAX_IMUSE_SOUNDS];
|
||||
|
||||
bool checkForProperHandle(SoundStruct *soundHandle);
|
||||
SoundStruct *allocSlot();
|
||||
void parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSize);
|
||||
bool checkForProperHandle(SoundDesc *soundDesc);
|
||||
SoundDesc *allocSlot();
|
||||
void parseSoundHeader(byte *ptr, SoundDesc *sound, int &headerSize);
|
||||
void countElements(byte *ptr, int &numRegions, int &numJumps);
|
||||
|
||||
public:
|
||||
@ -96,23 +97,23 @@ public:
|
||||
ImuseSndMgr();
|
||||
~ImuseSndMgr();
|
||||
|
||||
SoundStruct *openSound(const char *soundName, int volGroupId);
|
||||
void closeSound(SoundStruct *soundHandle);
|
||||
SoundStruct *cloneSound(SoundStruct *soundHandle);
|
||||
SoundDesc *openSound(const char *soundName, int volGroupId);
|
||||
void closeSound(SoundDesc *sound);
|
||||
SoundDesc *cloneSound(SoundDesc *sound);
|
||||
|
||||
int getFreq(SoundStruct *soundHandle);
|
||||
int getBits(SoundStruct *soundHandle);
|
||||
int getChannels(SoundStruct *soundHandle);
|
||||
bool isEndOfRegion(SoundStruct *soundHandle, int region);
|
||||
int getNumRegions(SoundStruct *soundHandle);
|
||||
int getNumJumps(SoundStruct *soundHandle);
|
||||
int getRegionOffset(SoundStruct *soundHandle, int region);
|
||||
int getJumpIdByRegionAndHookId(SoundStruct *soundHandle, int region, int hookId);
|
||||
int getRegionIdByJumpId(SoundStruct *soundHandle, int jumpId);
|
||||
int getJumpHookId(SoundStruct *soundHandle, int number);
|
||||
int getJumpFade(SoundStruct *soundHandle, int number);
|
||||
int getFreq(SoundDesc *sound);
|
||||
int getBits(SoundDesc *sound);
|
||||
int getChannels(SoundDesc *sound);
|
||||
bool isEndOfRegion(SoundDesc *sound, int region);
|
||||
int getNumRegions(SoundDesc *sound);
|
||||
int getNumJumps(SoundDesc *sound);
|
||||
int getRegionOffset(SoundDesc *sound, int region);
|
||||
int getJumpIdByRegionAndHookId(SoundDesc *sound, int region, int hookId);
|
||||
int getRegionIdByJumpId(SoundDesc *sound, int jumpId);
|
||||
int getJumpHookId(SoundDesc *sound, 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
|
||||
|
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/platform.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/mutex.h"
|
||||
|
||||
#include "engine/backend/driver.h"
|
||||
|
||||
@ -31,6 +32,7 @@
|
||||
|
||||
#include "engine/imuse/imuse.h"
|
||||
#include "engine/imuse/imuse_sndmgr.h"
|
||||
#include "engine/imuse/imuse_track.h"
|
||||
|
||||
int Imuse::allocSlot(int priority) {
|
||||
int l, lowest_priority = 127;
|
||||
@ -39,35 +41,46 @@ int Imuse::allocSlot(int priority) {
|
||||
// allocSlot called by startSound so no locking is necessary
|
||||
for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||
if (!_track[l]->used) {
|
||||
return l; // Found an unused track
|
||||
trackId = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
warning("Imuse::startSound(): All slots are full");
|
||||
for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
if (track->used && !track->toBeRemoved && lowest_priority > track->priority) {
|
||||
lowest_priority = track->priority;
|
||||
trackId = l;
|
||||
if (trackId == -1) {
|
||||
warning("Imuse::startSound(): All slots are full");
|
||||
for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
if (track->used && !track->toBeRemoved &&
|
||||
(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;
|
||||
}
|
||||
|
||||
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;
|
||||
int i, l = -1;
|
||||
|
||||
StackLock lock(_mutex);
|
||||
int i;
|
||||
|
||||
// If the track is already playing then there is absolutely no
|
||||
// reason to start it again, the existing track should be modified
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Priority Level 127 appears to mean "load but don't play", so
|
||||
// within our paradigm this is a much lower priority than everything
|
||||
// else we're doing
|
||||
if (priority == 127)
|
||||
priority = -1;
|
||||
l = allocSlot(priority);
|
||||
|
||||
int l = allocSlot(priority);
|
||||
if (l == -1) {
|
||||
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);
|
||||
warning("Imuse::startSound() Can't start sound - no free slots");
|
||||
return false;
|
||||
}
|
||||
|
||||
track = _track[l];
|
||||
// Reset the track
|
||||
memset(track, 0, sizeof(Track));
|
||||
|
||||
track->pan = pan * 1000;
|
||||
track->panFadeDest = 0;
|
||||
track->panFadeStep = 0;
|
||||
track->panFadeDelay = 0;
|
||||
track->panFadeUsed = false;
|
||||
track->vol = volume * 1000;
|
||||
track->volFadeDest = 0;
|
||||
track->volFadeStep = 0;
|
||||
track->volFadeDelay = 0;
|
||||
track->volFadeUsed = false;
|
||||
track->started = false;
|
||||
track->volGroupId = volGroupId;
|
||||
track->curHookId = hookId;
|
||||
track->priority = priority;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
bits = _sound->getBits(track->soundHandle);
|
||||
channels = _sound->getChannels(track->soundHandle);
|
||||
freq = _sound->getFreq(track->soundHandle);
|
||||
bits = _sound->getBits(track->soundDesc);
|
||||
channels = _sound->getChannels(track->soundDesc);
|
||||
freq = _sound->getFreq(track->soundDesc);
|
||||
|
||||
assert(bits == 8 || bits == 12 || bits == 16);
|
||||
assert(channels == 1 || channels == 2);
|
||||
assert(0 < freq && freq <= 65535);
|
||||
|
||||
track->iteration = freq * channels * 2;
|
||||
track->mixerFlags = SoundMixer::FLAG_16BITS;
|
||||
track->feedSize = freq * channels * 2;
|
||||
track->mixerFlags = kFlag16Bits;
|
||||
if (channels == 2)
|
||||
track->mixerFlags |= SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO;
|
||||
track->mixerFlags |= kFlagStereo | kFlagReverseStereo;
|
||||
|
||||
pan = track->pan / 1000;
|
||||
pan = (pan != 64) ? 2 * pan - 127 : 0;
|
||||
volume = track->vol / 1000;
|
||||
if (otherTrack && otherTrack->used && !otherTrack->toBeRemoved) {
|
||||
track->curRegion = otherTrack->curRegion;
|
||||
track->dataOffset = otherTrack->dataOffset;
|
||||
track->regionOffset = otherTrack->regionOffset;
|
||||
}
|
||||
|
||||
if (track->volGroupId == 1)
|
||||
volume = (volume * _volVoice) / 128;
|
||||
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->stream = Audio::makeAppendableAudioStream(freq, makeMixerFlags(track->mixerFlags));
|
||||
g_mixer->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
|
||||
track->used = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Imuse::Track *Imuse::findTrack(const char *soundName) {
|
||||
StackLock lock(_mutex);
|
||||
Track *Imuse::findTrack(const char *soundName) {
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
|
||||
// Since the audio (at least for Eva's keystrokes) can be referenced
|
||||
// two ways: keyboard.IMU and keyboard.imu, make a case insensitive
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@ -191,6 +166,7 @@ Imuse::Track *Imuse::findTrack(const char *soundName) {
|
||||
}
|
||||
|
||||
void Imuse::setPriority(const char *soundName, int priority) {
|
||||
Common::StackLock lock(_mutex);
|
||||
Track *changeTrack = NULL;
|
||||
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) {
|
||||
Common::StackLock lock(_mutex);
|
||||
Track *changeTrack;
|
||||
|
||||
changeTrack = findTrack(soundName);
|
||||
@ -215,17 +192,19 @@ void Imuse::setVolume(const char *soundName, int volume) {
|
||||
}
|
||||
|
||||
void Imuse::setPan(const char *soundName, int pan) {
|
||||
Common::StackLock lock(_mutex);
|
||||
Track *changeTrack;
|
||||
|
||||
changeTrack = findTrack(soundName);
|
||||
if (changeTrack == NULL) {
|
||||
warning("Unable to find track '%s' to change volume!", soundName);
|
||||
warning("Unable to find track '%s' to change pan!", soundName);
|
||||
return;
|
||||
}
|
||||
changeTrack->pan = pan;
|
||||
changeTrack->pan = pan * 1000;
|
||||
}
|
||||
|
||||
int Imuse::getVolume(const char *soundName) {
|
||||
Common::StackLock lock(_mutex);
|
||||
Track *getTrack;
|
||||
|
||||
getTrack = findTrack(soundName);
|
||||
@ -237,6 +216,7 @@ int Imuse::getVolume(const char *soundName) {
|
||||
}
|
||||
|
||||
void Imuse::setHookId(const char *soundName, int hookId) {
|
||||
Common::StackLock lock(_mutex);
|
||||
Track *changeTrack;
|
||||
|
||||
changeTrack = findTrack(soundName);
|
||||
@ -248,12 +228,12 @@ void Imuse::setHookId(const char *soundName, int hookId) {
|
||||
}
|
||||
|
||||
int Imuse::getCountPlayedTracks(const char *soundName) {
|
||||
Common::StackLock lock(_mutex);
|
||||
int count = 0;
|
||||
|
||||
StackLock lock(_mutex);
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS; 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++;
|
||||
}
|
||||
}
|
||||
@ -262,6 +242,7 @@ int Imuse::getCountPlayedTracks(const char *soundName) {
|
||||
}
|
||||
|
||||
void Imuse::selectVolumeGroup(const char *soundName, int volGroupId) {
|
||||
Common::StackLock lock(_mutex);
|
||||
Track *changeTrack;
|
||||
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) {
|
||||
Common::StackLock lock(_mutex);
|
||||
Track *changeTrack;
|
||||
|
||||
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) {
|
||||
Common::StackLock lock(_mutex);
|
||||
Track *changeTrack;
|
||||
|
||||
changeTrack = findTrack(soundName);
|
||||
@ -305,7 +288,7 @@ void Imuse::setFadePan(const char *soundName, int destPan, int duration) {
|
||||
}
|
||||
|
||||
char *Imuse::getCurMusicSoundName() {
|
||||
StackLock lock(_mutex);
|
||||
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)) {
|
||||
@ -315,65 +298,90 @@ char *Imuse::getCurMusicSoundName() {
|
||||
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) {
|
||||
StackLock lock(_mutex);
|
||||
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)) {
|
||||
cloneToFadeOutTrack(track, duration);
|
||||
track->toBeRemoved = true;
|
||||
flushTrack(track);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Imuse::Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
|
||||
assert(track);
|
||||
Track *fadeTrack = 0;
|
||||
void Imuse::fadeOutMusicAndStartNew(int fadeDelay, const char *filename, int hookId, int vol, int pan) {
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
{
|
||||
StackLock lock(_mutex);
|
||||
for (int l = MAX_IMUSE_TRACKS; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
if (!_track[l]->used) {
|
||||
fadeTrack = _track[l];
|
||||
break;
|
||||
}
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
|
||||
startMusicWithOtherPos(filename, 0, vol, pan, track);
|
||||
cloneToFadeOutTrack(track, fadeDelay);
|
||||
flushTrack(track);
|
||||
break;
|
||||
}
|
||||
if (fadeTrack == 0)
|
||||
error("Imuse::cloneTofadeTrackId() Can't find free fade track");
|
||||
}
|
||||
}
|
||||
|
||||
fadeTrack->pan = track->pan;
|
||||
fadeTrack->vol = track->vol;
|
||||
fadeTrack->volGroupId = track->volGroupId;
|
||||
fadeTrack->priority = track->priority;
|
||||
fadeTrack->dataOffset = track->dataOffset;
|
||||
fadeTrack->regionOffset = track->regionOffset;
|
||||
fadeTrack->curRegion = track->curRegion;
|
||||
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;
|
||||
Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
|
||||
assert(track);
|
||||
Track *fadeTrack;
|
||||
|
||||
if (track->toBeRemoved) {
|
||||
error("cloneToFadeOutTrack: Tried to clone a track to be removed, please bug report");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// setup 1 second stream wrapped buffer
|
||||
int32 streamBufferSize = fadeTrack->iteration;
|
||||
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);
|
||||
fadeTrack->started = true;
|
||||
assert(track->trackId < MAX_IMUSE_TRACKS);
|
||||
fadeTrack = _track[track->trackId + MAX_IMUSE_TRACKS];
|
||||
|
||||
if (fadeTrack->used) {
|
||||
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;
|
||||
|
||||
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 "mixer/mixer.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include <zlib.h>
|
||||
@ -1880,7 +1882,7 @@ static void ImStartSound() {
|
||||
group = check_int(3);
|
||||
|
||||
// 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);
|
||||
} else {
|
||||
// Allow soft failing when loading sounds, hard failing when not
|
||||
@ -1929,32 +1931,32 @@ static void ImSetVoiceEffect() {
|
||||
|
||||
static void ImSetMusicVol() {
|
||||
DEBUG_FUNCTION();
|
||||
g_imuse->setGroupMusicVolume(check_int(1));
|
||||
g_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, check_int(1));
|
||||
}
|
||||
|
||||
static void ImGetMusicVol() {
|
||||
DEBUG_FUNCTION();
|
||||
lua_pushnumber(g_imuse->getGroupMusicVolume());
|
||||
lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType));
|
||||
}
|
||||
|
||||
static void ImSetVoiceVol() {
|
||||
DEBUG_FUNCTION();
|
||||
g_imuse->setGroupVoiceVolume(check_int(1));
|
||||
g_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, check_int(1));
|
||||
}
|
||||
|
||||
static void ImGetVoiceVol() {
|
||||
DEBUG_FUNCTION();
|
||||
lua_pushnumber(g_imuse->getGroupVoiceVolume());
|
||||
lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType));
|
||||
}
|
||||
|
||||
static void ImSetSfxVol() {
|
||||
DEBUG_FUNCTION();
|
||||
g_imuse->setGroupSfxVolume(check_int(1));
|
||||
g_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, check_int(1));
|
||||
}
|
||||
|
||||
static void ImGetSfxVol() {
|
||||
DEBUG_FUNCTION();
|
||||
lua_pushnumber(g_imuse->getGroupSfxVolume());
|
||||
lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType));
|
||||
}
|
||||
|
||||
static void ImSetParam() {
|
||||
@ -2961,7 +2963,7 @@ static void GetSaveGameImage() {
|
||||
filename = luaL_check_string(1);
|
||||
SaveGame *savedState = new SaveGame(filename, false);
|
||||
dataSize = savedState->beginSection('SIMG');
|
||||
data = (char *)malloc(dataSize);
|
||||
data = new char[dataSize];
|
||||
savedState->read(data, dataSize);
|
||||
screenshot = new Bitmap(data, width, height, "screenshot");
|
||||
if (screenshot) {
|
||||
|
@ -58,6 +58,8 @@ enDebugLevels debugLevel = DEBUG_NONE;
|
||||
|
||||
static bool g_lua_initialized = false;
|
||||
Driver *g_driver = NULL;
|
||||
DefaultTimerManager *g_timer = NULL;
|
||||
Audio::Mixer *g_mixer = NULL;
|
||||
|
||||
static bool parseBoolStr(const char *val) {
|
||||
if (val == NULL || val[0] == 0)
|
||||
@ -168,12 +170,18 @@ needshelp:
|
||||
g_driver = new DriverTinyGL(640, 480, 16, fullscreen);
|
||||
else
|
||||
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_resourceloader = new ResourceLoader();
|
||||
g_localizer = new Localizer();
|
||||
g_mixer = new SoundMixer();
|
||||
g_mixer->setVolume(255);
|
||||
g_timer = new Timer();
|
||||
g_smush = new Smush();
|
||||
g_imuse = new Imuse(20);
|
||||
|
||||
@ -226,6 +234,8 @@ void quit() {
|
||||
delete g_registry;
|
||||
g_registry = NULL;
|
||||
}
|
||||
if (g_driver)
|
||||
g_driver->clearTimerCallback();
|
||||
delete g_smush;
|
||||
g_smush = NULL;
|
||||
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!");
|
||||
_currentSection = sectionTag;
|
||||
_sectionSize = 0;
|
||||
_sectionBuffer = (char *) malloc(_sectionSize);
|
||||
_sectionBuffer = new char[_sectionSize];
|
||||
if (!_saving) {
|
||||
uint32 tag = 0;
|
||||
|
||||
while (tag != sectionTag) {
|
||||
free(_sectionBuffer);
|
||||
delete[] _sectionBuffer;
|
||||
gzread(_fileHandle, &tag, sizeof(uint32));
|
||||
if (tag == SAVEGAME_FOOTERTAG)
|
||||
error("Unable to find requested section of savegame!");
|
||||
gzread(_fileHandle, &_sectionSize, sizeof(uint32));
|
||||
_sectionBuffer = (char *)malloc(_sectionSize);
|
||||
_sectionBuffer = new char[_sectionSize];
|
||||
gzread(_fileHandle, _sectionBuffer, _sectionSize);
|
||||
}
|
||||
}
|
||||
@ -94,8 +94,8 @@ void SaveGame::endSection() {
|
||||
gzwrite(_fileHandle, &_sectionSize, sizeof(uint32));
|
||||
gzwrite(_fileHandle, _sectionBuffer, _sectionSize);
|
||||
}
|
||||
free(_sectionBuffer);
|
||||
_currentSection = 0;
|
||||
delete[] _sectionBuffer;
|
||||
_currentSection = NULL;
|
||||
}
|
||||
|
||||
void SaveGame::read(void *data, int size) {
|
||||
|
@ -624,7 +624,7 @@ void Blocky16::init(int width, int height) {
|
||||
// lol, byeruba, crushed, eldepot, heltrain, hostage
|
||||
// but for tb_kitty.snm 5700 bytes is needed
|
||||
_deltaSize = _frameSize * 3 + 5700;
|
||||
_deltaBuf = (byte *)malloc(_deltaSize);
|
||||
_deltaBuf = new byte[_deltaSize];
|
||||
memset(_deltaBuf, 0, _deltaSize);
|
||||
_deltaBufs[0] = _deltaBuf;
|
||||
_deltaBufs[1] = _deltaBuf + _frameSize;
|
||||
@ -632,8 +632,8 @@ void Blocky16::init(int width, int height) {
|
||||
}
|
||||
|
||||
Blocky16::Blocky16() {
|
||||
_tableBig = (byte *)malloc(99328);
|
||||
_tableSmall = (byte *)malloc(32768);
|
||||
_tableBig = new byte[99328];
|
||||
_tableSmall = new byte[32768];
|
||||
memset(_tableBig, 0, 99328);
|
||||
memset(_tableSmall, 0, 32768);
|
||||
_deltaBuf = NULL;
|
||||
@ -642,7 +642,7 @@ Blocky16::Blocky16() {
|
||||
void Blocky16::deinit() {
|
||||
_lastTableWidth = -1;
|
||||
if (_deltaBuf) {
|
||||
free(_deltaBuf);
|
||||
delete[] _deltaBuf;
|
||||
_deltaSize = 0;
|
||||
_deltaBuf = NULL;
|
||||
_deltaBufs[0] = NULL;
|
||||
@ -653,11 +653,11 @@ void Blocky16::deinit() {
|
||||
Blocky16::~Blocky16() {
|
||||
deinit();
|
||||
if (_tableBig) {
|
||||
free(_tableBig);
|
||||
delete[] _tableBig;
|
||||
_tableBig = NULL;
|
||||
}
|
||||
if (_tableSmall) {
|
||||
free(_tableSmall);
|
||||
delete[] _tableSmall;
|
||||
_tableSmall = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "engine/resource.h"
|
||||
#include "engine/engine.h"
|
||||
#include "engine/backend/driver.h"
|
||||
#include "engine/imuse/imuse_track.h"
|
||||
|
||||
#include "mixer/mixer.h"
|
||||
|
||||
@ -83,8 +84,8 @@ void Smush::init() {
|
||||
assert(!_internalBuffer);
|
||||
assert(!_externalBuffer);
|
||||
|
||||
_internalBuffer = (byte *)malloc(_width * _height * 2);
|
||||
_externalBuffer = (byte *)malloc(_width * _height * 2);
|
||||
_internalBuffer = new byte[_width * _height * 2];
|
||||
_externalBuffer = new byte[_width * _height * 2];
|
||||
|
||||
vimaInit(smushDestTable);
|
||||
g_timer->installTimerProc(&timerCallback, _speed, NULL);
|
||||
@ -94,16 +95,16 @@ void Smush::deinit() {
|
||||
g_timer->removeTimerProc(&timerCallback);
|
||||
|
||||
if (_internalBuffer) {
|
||||
free(_internalBuffer);
|
||||
delete[] _internalBuffer;
|
||||
_internalBuffer = NULL;
|
||||
}
|
||||
if (_externalBuffer) {
|
||||
free(_externalBuffer);
|
||||
delete[] _externalBuffer;
|
||||
_externalBuffer = NULL;
|
||||
}
|
||||
if (_videoLooping && _startPos != NULL) {
|
||||
free(_startPos->tmpBuf);
|
||||
free(_startPos);
|
||||
delete[] _startPos->tmpBuf;
|
||||
delete[] _startPos;
|
||||
_startPos = NULL;
|
||||
}
|
||||
if (_stream) {
|
||||
@ -118,20 +119,22 @@ void Smush::deinit() {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
int flags = SoundMixer::FLAG_16BITS;
|
||||
int flags = Audio::Mixer::FLAG_16BITS;
|
||||
if (_channels == 2)
|
||||
flags |= SoundMixer::FLAG_STEREO;
|
||||
flags |= Audio::Mixer::FLAG_STEREO;
|
||||
|
||||
if (!_stream) {
|
||||
_stream = makeAppendableAudioStream(_freq, flags, 500000);
|
||||
g_mixer->playInputStream(&_soundHandle, _stream, true);
|
||||
_stream = Audio::makeAppendableAudioStream(_freq, flags);
|
||||
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() {
|
||||
@ -162,7 +165,7 @@ void Smush::handleFrame() {
|
||||
byte *data;
|
||||
|
||||
size = _file.readUint32BE();
|
||||
data = (byte *)malloc(size);
|
||||
data = new byte[size];
|
||||
_file.read(data, size);
|
||||
anno = (char *)data;
|
||||
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)
|
||||
printf("Announcement header not understood: %s\n", anno);
|
||||
}
|
||||
free(anno);
|
||||
delete[] anno;
|
||||
tag = _file.readUint32BE();
|
||||
}
|
||||
|
||||
assert(tag == MKID_BE('FRME'));
|
||||
size = _file.readUint32BE();
|
||||
byte *frame = (byte *)malloc(size);
|
||||
byte *frame = new byte[size];
|
||||
_file.read(frame, size);
|
||||
|
||||
do {
|
||||
@ -209,7 +212,7 @@ void Smush::handleFrame() {
|
||||
error("Smush::handleFrame() unknown tag");
|
||||
}
|
||||
} while (pos < size);
|
||||
free(frame);
|
||||
delete[] frame;
|
||||
|
||||
memcpy(_externalBuffer, _internalBuffer, _width * _height * 2);
|
||||
_updateNeeded = true;
|
||||
@ -234,7 +237,7 @@ void Smush::handleFramesHeader() {
|
||||
tag = _file.readUint32BE();
|
||||
assert(tag == MKID_BE('FLHD'));
|
||||
size = _file.readUint32BE();
|
||||
byte *f_header = (byte*)malloc(size);
|
||||
byte *f_header = new byte[size];
|
||||
_file.read(f_header, size);
|
||||
|
||||
do {
|
||||
@ -248,7 +251,7 @@ void Smush::handleFramesHeader() {
|
||||
error("Smush::handleFramesHeader() unknown tag");
|
||||
}
|
||||
} while (pos < size);
|
||||
free(f_header);
|
||||
delete[] f_header;
|
||||
}
|
||||
|
||||
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'));
|
||||
|
||||
size = _file.readUint32BE();
|
||||
byte *s_header = (byte *)malloc(size);
|
||||
byte *s_header = new byte[size];
|
||||
_file.read(s_header, size);
|
||||
_nbframes = READ_LE_UINT32(s_header + 2);
|
||||
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);
|
||||
_startPos = NULL; // Set later
|
||||
free(s_header);
|
||||
delete[] s_header;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -347,10 +350,10 @@ struct SavePos *zlibFile::getPos() {
|
||||
warning("zlibFile::open() unable to find start position! %m");
|
||||
return NULL;
|
||||
}
|
||||
pos = (struct SavePos *) malloc(sizeof(struct SavePos));
|
||||
pos = new SavePos;
|
||||
pos->filePos = position;
|
||||
inflateCopy(&pos->streamBuf, &_stream);
|
||||
pos->tmpBuf = (char *)calloc(1, BUFFER_SIZE);
|
||||
pos->tmpBuf = new char[BUFFER_SIZE];
|
||||
memcpy(pos->tmpBuf, _inBuf, BUFFER_SIZE);
|
||||
return pos;
|
||||
}
|
||||
@ -446,7 +449,7 @@ void zlibFile::close() {
|
||||
}
|
||||
|
||||
if (_inBuf) {
|
||||
free(_inBuf);
|
||||
delete[] _inBuf;
|
||||
_inBuf = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -70,8 +70,8 @@ private:
|
||||
int32 _nbframes;
|
||||
Blocky16 _blocky16;
|
||||
zlibFile _file;
|
||||
PlayingSoundHandle _soundHandle;
|
||||
AppendableAudioStream *_stream;
|
||||
Audio::SoundHandle _soundHandle;
|
||||
Audio::AppendableAudioStream *_stream;
|
||||
|
||||
int32 _frame;
|
||||
bool _updateNeeded;
|
||||
|
@ -139,7 +139,7 @@ void TextObject::createBitmap() {
|
||||
message += msg[i];
|
||||
}
|
||||
_textObjectHandle = (Driver::TextObjectHandle **)malloc(sizeof(long) * _numberLines);
|
||||
_bitmapWidthPtr = (int *)malloc(sizeof(int) * _numberLines);
|
||||
_bitmapWidthPtr = new int[_numberLines];
|
||||
|
||||
for (int j = 0; j < _numberLines; j++) {
|
||||
int nextLinePos = message.find_first_of('\n');
|
||||
@ -188,13 +188,13 @@ void TextObject::destroyBitmap() {
|
||||
if (_textObjectHandle) {
|
||||
for (int i = 0; i < _numberLines; i++) {
|
||||
g_driver->destroyTextBitmap(_textObjectHandle[i]);
|
||||
delete _textObjectHandle[i];
|
||||
delete[] _textObjectHandle[i];
|
||||
}
|
||||
free(_textObjectHandle);
|
||||
_textObjectHandle = NULL;
|
||||
}
|
||||
if (_bitmapWidthPtr) {
|
||||
free(_bitmapWidthPtr);
|
||||
delete[] _bitmapWidthPtr;
|
||||
_bitmapWidthPtr = NULL;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user