aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2012-06-19 20:50:48 +1000
committerPaul Gilbert2012-06-19 20:50:48 +1000
commit61d460a854ff4883411846703543bb2f797fcd6b (patch)
tree48d146adf7a2df49faa290a8ef9c38e66eb25c83 /engines
parent0aa3d39cf7034dc35cda9e5062469886b0eb74d2 (diff)
downloadscummvm-rg350-61d460a854ff4883411846703543bb2f797fcd6b.tar.gz
scummvm-rg350-61d460a854ff4883411846703543bb2f797fcd6b.tar.bz2
scummvm-rg350-61d460a854ff4883411846703543bb2f797fcd6b.zip
TONY: Implement more of the music related code from the original
Diffstat (limited to 'engines')
-rw-r--r--engines/tony/custom.cpp6
-rw-r--r--engines/tony/gfxengine.cpp2
-rw-r--r--engines/tony/sound.cpp809
-rw-r--r--engines/tony/sound.h35
-rw-r--r--engines/tony/tony.cpp99
-rw-r--r--engines/tony/tony.h4
6 files changed, 671 insertions, 284 deletions
diff --git a/engines/tony/custom.cpp b/engines/tony/custom.cpp
index 016c84ab39..ce1c2860f8 100644
--- a/engines/tony/custom.cpp
+++ b/engines/tony/custom.cpp
@@ -2198,14 +2198,14 @@ DECLARE_CUSTOM_FUNCTION(DemuteJingle)(CORO_PARAM, uint32, uint32, uint32, uint32
void CustPlayMusic(uint32 nChannel, const char *mFN, uint32 nFX, bool bLoop, int nSync = 0) {
if (nSync == 0)
nSync = 2000;
- debug("Start CustPlayMusic");
+ debugC(DEBUG_INTERMEDIATE, kTonyDebugMusic, "Start CustPlayMusic");
GLOBALS.PlayMusic(nChannel, mFN, nFX, bLoop, nSync);
- debug("End CustPlayMusic");
+ debugC(DEBUG_INTERMEDIATE, kTonyDebugMusic, "End CustPlayMusic");
}
DECLARE_CUSTOM_FUNCTION(PlaySoundEffect)(CORO_PARAM, uint32 nMusic, uint32 nFX, uint32 bNoLoop, uint32) {
if (nFX == 0 || nFX == 1 || nFX == 2) {
- debug("PlaySoundEffect stop fadeout");
+ debugC(DEBUG_INTERMEDIATE, kTonyDebugSound, "PlaySoundEffect stop fadeout");
GLOBALS._bFadeOutStop = true;
}
diff --git a/engines/tony/gfxengine.cpp b/engines/tony/gfxengine.cpp
index 0785ec534c..cc53a1d8e2 100644
--- a/engines/tony/gfxengine.cpp
+++ b/engines/tony/gfxengine.cpp
@@ -473,8 +473,6 @@ void RMGfxEngine::init() {
delete load;
// Display 'Loading' screen
- // TODO: The loading screen isn't currently optimal, since the game doesn't respond to events
- // whilst the mpalInit code is being executed.
_vm->_window.getNewFrame(*this, NULL);
_vm->_window.repaint();
diff --git a/engines/tony/sound.cpp b/engines/tony/sound.cpp
index 7e786a2f11..484b279cda 100644
--- a/engines/tony/sound.cpp
+++ b/engines/tony/sound.cpp
@@ -39,11 +39,406 @@ namespace Tony {
#define RELEASE(x) {if ((x) != NULL) { (x)->release(); x = NULL; }}
+
+/****************************************************************************\
+*****************************************************************************
+* class CODECRAW
+* --------------
+* Description: CODEC to play hard from pure samples
+*****************************************************************************
+\****************************************************************************/
+
+class CODECRAW : public CODEC {
+public:
+ CODECRAW(bool _bLoop = true);
+
+ virtual ~CODECRAW();
+ virtual uint32 decompress(Common::SeekableReadStream *stream, void *lpBuf, uint32 dwSize);
+ virtual void loopReset();
+};
+
+
+/****************************************************************************\
+*****************************************************************************
+* class CODECADPCM
+* ----------------
+* Description: Play ADPCM compressed data
+*****************************************************************************
+\****************************************************************************/
+
+class CODECADPCM : public CODECRAW {
+protected:
+ byte *lpTemp;
+ static const int indexTable[16];
+ static const int stepSizeTable[89];
+
+public:
+ CODECADPCM(bool _bLoop = true, byte *lpTempBuffer = NULL);
+ virtual ~CODECADPCM();
+ virtual uint32 decompress(Common::SeekableReadStream *stream, void *lpBuf, uint32 dwSize) = 0;
+ virtual void loopReset() = 0;
+};
+
+class CODECADPCMSTEREO : public CODECADPCM {
+protected:
+ int valpred[2], index[2];
+
+public:
+ CODECADPCMSTEREO(bool _bLoop=true, byte *lpTempBuffer = NULL);
+ virtual ~CODECADPCMSTEREO();
+ virtual uint32 decompress(Common::SeekableReadStream *stream, void *lpBuf, uint32 dwSize);
+ virtual void loopReset();
+};
+
+class CODECADPCMMONO : public CODECADPCM {
+protected:
+ int valpred, index;
+
+public:
+ CODECADPCMMONO(bool _bLoop = true, byte *lpTempBuffer = NULL);
+ virtual ~CODECADPCMMONO();
+ virtual uint32 decompress(Common::SeekableReadStream *stream, void *lpBuf, uint32 dwSize);
+ virtual void loopReset();
+};
+
+/****************************************************************************\
+* CODEC Methods
+\****************************************************************************/
+
/**
- * Default constructor. Initializes the attributes.
+ * Standard cosntructor. It's possible to specify whether you want to
+ * enable or disable the loop (which by default, and 'active).
+ *
+ * @param loop True if you want to loop, false to disable
+ */
+CODEC::CODEC(bool loop) {
+ _bLoop = loop;
+ _bEndReached = false;
+}
+
+CODEC::~CODEC() {
+}
+
+/**
+ * Tell whether we have reached the end of the stream
*
+ * @return True if we're done, false otherwise.
+ */
+bool CODEC::endOfStream() {
+ return _bEndReached;
+}
+
+
+/****************************************************************************\
+* CODECRAW Methods
+\****************************************************************************/
+
+/**
+ * Standard cosntructor. Simply calls the inherited constructor
+ */
+CODECRAW::CODECRAW(bool loop) : CODEC(loop) {
+}
+
+CODECRAW::~CODECRAW() {
+}
+
+/**
+ * Reset the stream to the beginning of the file. In the case of RAW files, does nothing
+ */
+void CODECRAW::loopReset() {
+}
+
+/**
+ * Manage the RAW format. Simply copies the file's stream buffer
+ *
+ * @return Indicates the position of the file for the end of the loop
+ */
+uint32 CODECRAW::decompress(Common::SeekableReadStream *stream, void *buf, uint32 dwSize) {
+ byte *lpBuf = (byte *)buf;
+ uint32 dwRead;
+ uint32 dwEOF;
+
+ _bEndReached = false;
+ dwEOF = 0;
+ dwRead = stream->read(lpBuf, dwSize);
+
+ if (dwRead < dwSize) {
+ dwEOF = dwRead;
+ _bEndReached = true;
+
+ if (!_bLoop) {
+ Common::fill(lpBuf + dwRead, lpBuf + dwRead + (dwSize - dwRead), 0);
+ } else {
+ stream->seek(0);
+ dwRead = stream->read(lpBuf + dwRead, dwSize - dwRead);
+ }
+ }
+
+ return dwEOF;
+}
+
+/****************************************************************************\
+* CODECADPCM Methods
+\****************************************************************************/
+
+const int CODECADPCM::indexTable[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8,
+};
+
+const int CODECADPCM::stepSizeTable[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+#define MAXDECODESIZE (44100 * 2 * 2)
+
+/**
+ * Standard constructor. Initialises and allocates temporary memory tables
+ */
+CODECADPCM::CODECADPCM(bool loop, byte *lpTempBuffer) : CODECRAW(loop) {
+ // Alloca la memoria temporanea
+ if (lpTempBuffer != NULL) {
+ lpTemp = lpTempBuffer;
+ } else {
+ lpTemp = (byte *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, MAXDECODESIZE);
+
+ if (lpTemp == NULL) {
+ error("Insufficient memory!");
+ return;
+ }
+ }
+}
+
+
+CODECADPCMMONO::CODECADPCMMONO(bool loop, byte *lpTempBuffer) : CODECADPCM(loop,lpTempBuffer) {
+ // Inizializza per il playing
+ loopReset();
+}
+
+CODECADPCMMONO::~CODECADPCMMONO() {
+}
+
+
+CODECADPCMSTEREO::CODECADPCMSTEREO(bool loop, byte *lpTempBuffer) : CODECADPCM(loop, lpTempBuffer) {
+ // Initialise for playing
+ loopReset();
+}
+
+CODECADPCMSTEREO::~CODECADPCMSTEREO() {
+}
+
+/**
+ * Destructor. Free the buffer
+ */
+CODECADPCM::~CODECADPCM() {
+ globalDestroy(lpTemp);
+}
+
+
+/**
+ * Reset the player before each play or loop
+ */
+void CODECADPCMSTEREO::loopReset() {
+ valpred[0] = 0;
+ valpred[1] = 0;
+ index[0] = 0;
+ index[1] = 0;
+}
+
+void CODECADPCMMONO::loopReset() {
+ valpred = 0;
+ index = 0;
+}
+
+
+/**
+ * Manages decompressing the ADPCM 16:4 format.
*/
+uint32 CODECADPCMMONO::decompress(Common::SeekableReadStream *stream, void *buf, uint32 dwSize) {
+ uint16 *lpBuf = (uint16 *)buf;
+ byte *inp;
+ int bufferstep;
+ int cache;
+ int delta;
+ int sign;
+ int vpdiff;
+ uint32 eof, i;
+ int step;
+
+ bufferstep = 1;
+ step = stepSizeTable[index];
+
+ // Invokes the raw codec to read the stream from disk to loop.
+ eof = CODECRAW::decompress(stream, lpTemp, dwSize / 4);
+ inp = lpTemp;
+
+ eof *= 2;
+
+ // If you must do an immediate loop
+ if (endOfStream() && eof == 0) {
+ loopReset();
+ bufferstep = 1;
+ step = stepSizeTable[index];
+ } else if (!endOfStream())
+ eof = 0;
+
+ dwSize /= 2;
+ for (i = 0; i < dwSize; i++) {
+ // Check if we are at the end of the file, and are looping
+ if (eof != 0 && i == eof) {
+ loopReset();
+ bufferstep=1;
+ step = stepSizeTable[index];
+ }
+
+ // Read the delta (4 bits)
+ if (bufferstep) {
+ cache = *inp++;
+ delta = (cache >> 4) & 0xF;
+ } else
+ delta = cache & 0xF;
+
+ // Find the new index
+ index += indexTable[delta];
+ if (index < 0) index = 0;
+ if (index > 88) index = 88;
+
+ // Reads the sign and separates it
+ sign = delta & 8;
+ delta = delta & 7;
+
+ // Find the difference from the previous value
+ vpdiff = step >> 3;
+ if (delta & 4) vpdiff += step;
+ if (delta & 2) vpdiff += step >> 1;
+ if (delta & 1) vpdiff += step >> 2;
+
+ if (sign)
+ valpred -= vpdiff;
+ else
+ valpred += vpdiff;
+
+ // Check the limits of the found value
+ if (valpred > 32767)
+ valpred = 32767;
+ else if (valpred < -32768)
+ valpred = -32768;
+
+ // Update the step
+ step = stepSizeTable[index];
+
+ // Write the value found
+ *lpBuf++ = (uint16)valpred;
+
+ bufferstep = !bufferstep;
+ }
+
+ return eof / 2;
+}
+
+uint32 CODECADPCMSTEREO::decompress(Common::SeekableReadStream *stream, void *buf, uint32 dwSize) {
+ uint16 *lpBuf=(uint16 *)buf;
+ byte *inp;
+ int bufferstep;
+ int cache;
+ int delta;
+ int sign;
+ int vpdiff;
+ uint32 eof, i;
+ int step[2];
+
+ bufferstep = 1;
+ step[0] = stepSizeTable[index[0]];
+ step[1] = stepSizeTable[index[1]];
+
+ // Invokes the RAW codec to read the stream from disk.
+ eof = CODECRAW::decompress(stream, lpTemp, dwSize / 4);
+ inp = lpTemp;
+
+ eof *= 2;
+
+ // If you must do an immediate loop
+ if (endOfStream() && eof == 0) {
+ loopReset();
+ bufferstep = 1;
+ step[0] = stepSizeTable[index[0]];
+ step[1] = stepSizeTable[index[1]];
+
+ } else if (!endOfStream())
+ eof = 0;
+
+ dwSize /= 2;
+
+ for (i = 0;i < dwSize; i++) {
+ // If you must do an immediate loop
+ if (eof != 0 && i == eof) {
+ loopReset();
+ bufferstep = 1;
+ step[0] = stepSizeTable[index[0]];
+ step[1] = stepSizeTable[index[1]];
+ }
+
+ // Reads the delta (4 bits)
+ if (bufferstep) {
+ cache = *inp++;
+ delta = cache & 0xF;
+ } else
+ delta = (cache >> 4) & 0xF;
+
+ // Find the new index
+ index[bufferstep] += indexTable[delta];
+ if (index[bufferstep] < 0) index[bufferstep] = 0;
+ if (index[bufferstep] > 88) index[bufferstep] = 88;
+
+ // Reads the sign and separates it
+ sign = delta & 8;
+ delta = delta & 7;
+
+ // Find the difference from the previous value
+ vpdiff = step[bufferstep] >> 3;
+ if (delta & 4) vpdiff += step[bufferstep];
+ if (delta & 2) vpdiff += step[bufferstep] >> 1;
+ if (delta & 1) vpdiff += step[bufferstep] >> 2;
+
+ if (sign)
+ valpred[bufferstep] -= vpdiff;
+ else
+ valpred[bufferstep] += vpdiff;
+
+ // Check the limits of the value
+ if (valpred[bufferstep] > 32767)
+ valpred[bufferstep] = 32767;
+ else if (valpred[bufferstep] < -32768)
+ valpred[bufferstep] =- 32768;
+
+ // Update the step
+ step[bufferstep] = stepSizeTable[index[bufferstep]];
+
+ // Write the found value
+ *lpBuf++ = (uint16)valpred[bufferstep];
+
+ bufferstep = !bufferstep;
+ }
+
+ return eof / 2;
+}
+
+/****************************************************************************\
+* FPSOUND Methods
+\****************************************************************************/
+/**
+ * Default constructor. Initializes the attributes.
+ *
+ */
FPSound::FPSound() {
_bSoundSupported = false;
}
@@ -53,7 +448,6 @@ FPSound::FPSound() {
*
* @returns True is everything is OK, False otherwise
*/
-
bool FPSound::init() {
_bSoundSupported = g_system->getMixer()->isReady();
return _bSoundSupported;
@@ -308,7 +702,7 @@ bool FPSfx::stop() {
/**
* Enables or disables the Sfx loop.
*
- * @param bLoop True to enable the loop, False to disable
+ * @param _bLoop True to enable the loop, False to disable
*
* @remarks The loop must be activated BEFORE the sfx starts
* playing. Any changes made during the play will have
@@ -423,20 +817,19 @@ void FPSfx::soundCheckProcess(CORO_PARAM, const void *param) {
* @remarks Do *NOT* declare an object directly, but rather
* create it using FPSound::CreateStream()
*/
-
FPStream::FPStream(bool bSoundOn) {
#ifdef REFACTOR_ME
- //hwnd=hWnd;
+ hwnd=hWnd;
lpDS = LPDS;
- bSoundSupported = bSoundOn;
- bFileLoaded = false;
- bIsPlaying = false;
- bPaused = false;
- bSyncExit = false;
- lpDSBuffer = NULL;
- lpDSNotify = NULL;
- hHot1 = hHot2 = hHot3 = hPlayThread_PlayFast = hPlayThread_PlayNormal = NULL;
+ _lpDSBuffer = NULL;
+ _lpDSNotify = NULL;
#endif
+ _bSoundSupported = bSoundOn;
+ _bFileLoaded = false;
+ _bIsPlaying = false;
+ _bPaused = false;
+ _bSyncExit = false;
+ _hHot1 = _hHot2 = _hHot3 = _hPlayThreadPlayFast = _hPlayThreadPlayNormal = CORO_INVALID_PID_VALUE;
}
bool FPStream::createBuffer(int nBufSize) {
@@ -512,40 +905,38 @@ bool FPStream::createBuffer(int nBufSize) {
*/
FPStream::~FPStream() {
-#ifdef REFACTOR_ME
-
- if (!bSoundSupported)
+ if (!_bSoundSupported)
return;
- if (bIsPlaying)
- Stop();
+ if (_bIsPlaying)
+ stop();
- if (bFileLoaded)
- UnloadFile();
+ if (_bFileLoaded)
+ unloadFile();
- if (hHot1) {
- CloseHandle(hHot1);
- hHot1 = NULL;
+ if (_hHot1) {
+ CoroScheduler.closeEvent(_hHot1);
+ _hHot1 = CORO_INVALID_PID_VALUE;
}
- if (hHot2) {
- CloseHandle(hHot2);
- hHot2 = NULL;
+ if (_hHot2) {
+ CoroScheduler.closeEvent(_hHot2);
+ _hHot2 = CORO_INVALID_PID_VALUE;
}
- if (hHot3) {
- CloseHandle(hHot3);
- hHot3 = NULL;
+ if (_hHot3) {
+ CoroScheduler.closeEvent(_hHot3);
+ _hHot3 = CORO_INVALID_PID_VALUE;
}
- if (hPlayThread_PlayFast) {
- CloseHandle(hPlayThread_PlayFast);
- hPlayThread_PlayFast = NULL;
+ if (_hPlayThreadPlayFast != CORO_INVALID_PID_VALUE) {
+ CoroScheduler.closeEvent(_hPlayThreadPlayFast);
+ _hPlayThreadPlayFast = CORO_INVALID_PID_VALUE;
}
- if (hPlayThread_PlayNormal) {
- CloseHandle(hPlayThread_PlayNormal);
- hPlayThread_PlayNormal = NULL;
+ if (_hPlayThreadPlayNormal != CORO_INVALID_PID_VALUE) {
+ CoroScheduler.closeEvent(_hPlayThreadPlayNormal);
+ _hPlayThreadPlayNormal = CORO_INVALID_PID_VALUE;
}
- SyncToPlay = NULL;
-
+ _syncToPlay = NULL;
+#ifdef REFACTOR_ME
RELEASE(lpDSNotify);
RELEASE(lpDSBuffer);
#endif
@@ -559,7 +950,6 @@ FPStream::~FPStream() {
* FPSound::CreateStream().
* Object pointers are no longer valid after this call.
*/
-
void FPStream::release() {
delete this;
}
@@ -567,44 +957,35 @@ void FPStream::release() {
/**
* Opens a file stream
*
- * @param lpszFile Filename to be opened
+ * @param fileName Filename to be opened
* @param dwCodec CODEC to be used to uncompress samples
*
* @returns True is everything is OK, False otherwise
*/
-
-bool FPStream::loadFile(const char *lpszFileName, uint32 dwCodType, int nBufSize) {
-#ifdef REFACTOR_ME
- HRESULT err;
- void *lpBuf;
- uint32 dwHi;
-
- if (!bSoundSupported)
+bool FPStream::loadFile(const Common::String &fileName, uint32 dwCodType, int nBufSize) {
+ if (!_bSoundSupported)
return true;
- /* Si salva il tipo di codec */
- dwCodec = dwCodType;
+ // Save the codec type
+ _dwCodec = dwCodType;
- /* Crea il buffer */
- if (!CreateBuffer(nBufSize))
+ // Create the buffer
+ if (!createBuffer(nBufSize))
return true;
- /* Apre il file di stream in lettura */
- if (!_file.open(lpszFileName))
- //MessageBox(hwnd,"Cannot open stream file!","FPStream::LoadFile()", MB_OK);
+ // Open the file stream for reading
+ if (!_file.open(fileName))
return false;
-}
-/* Si salva la lunghezza dello stream */
-dwSize = _file.size();
-_file.seek(0);
+ // Save the size of the stream
+ _dwSize = _file.size();
-/* Tutto a posto, possiamo uscire */
-bFileLoaded = true;
-bIsPlaying = false;
-bPaused = false;
-#endif
-return true;
+ // All done
+ _bFileLoaded = true;
+ _bIsPlaying = false;
+ _bPaused = false;
+
+ return true;
}
/**
@@ -616,85 +997,80 @@ return true;
* @remarks It is necessary to call this function to free the
* memory used by the stream.
*/
-
bool FPStream::unloadFile() {
-#ifdef REFACTOR_ME
-
- if (!bSoundSupported || !bFileLoaded)
+ if (!_bSoundSupported || !_bFileLoaded)
return true;
/* Closes the file handle stream */
_file.close();
-
+#ifdef REFACTOR_ME
RELEASE(lpDSNotify);
RELEASE(lpDSBuffer);
-
- /* Remember no more file is loaded in memory */
- bFileLoaded = false;
#endif
+
+ // Flag that the file is no longer in memory
+ _bFileLoaded = false;
+
return true;
}
void FPStream::prefetch() {
-#ifdef REFACTOR_ME
- uint32 dwId;
void *lpBuf;
- uint32 dwHi;
- HRESULT err;
- if (!bSoundSupported || !bFileLoaded)
+ if (!_bSoundSupported || !_bFileLoaded)
return;
- /* Allocates a temporary buffer */
- lpTempBuffer = (byte *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwBufferSize / 2);
- if (lpTempBuffer == NULL)
+ // Allocates a temporary buffer
+ _lpTempBuffer = (byte *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, _dwBufferSize / 2);
+ if (_lpTempBuffer == NULL)
return;
- switch (dwCodec) {
- case FPCODEC_RAW:
- lpCodec = new CODECRAW(bLoop);
- break;
-
- case FPCODEC_ADPCM:
- lpCodec = new CODECADPCMSTEREO(bLoop);
- break;
-
- default:
+ if (_dwCodec == FPCODEC_RAW) {
+ _codec = new CODECRAW(_bLoop);
+ } else if (_dwCodec == FPCODEC_ADPCM) {
+ _codec = new CODECADPCMSTEREO(_bLoop);
+ } else {
return;
}
- /* reset the file position */
+ // reset the file position
_file.seek(0);
- /* Fills the buffer for the data already ready */
+#ifdef REFACTOR_ME
+ // Fills the buffer for the data already ready
if ((err = lpDSBuffer->Lock(0, dwBufferSize / 2, &lpBuf, (uint32 *)&dwHi, NULL, NULL, 0)) != DS_OK) {
- MessageBox(hwnd, "Cannot lock stream buffer!", "soundLoadStream()", MB_OK);
+ _vm->GUIError("Cannot lock stream buffer!", "soundLoadStream()");
return;
}
+#endif
- /* Uncompress the data from the stream directly into the locked buffer */
- lpCodec->Decompress(hFile, lpBuf, dwBufferSize / 2);
-
- /* Unlock the buffer */
- lpDSBuffer->Unlock(lpBuf, dwBufferSize / 2, NULL, NULL);
+ // Uncompress the data from the stream directly into the locked buffer
+ _codec->decompress(_file.readStream(_file.size()), lpBuf, _dwBufferSize / 2);
- /* Create a thread to play the stream */
- hThreadEnd = CreateEvent(NULL, false, false, NULL);
- hPlayThread = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)PlayThread, (void *)this, 0, &dwId);
- SetThreadPriority(hPlayThread, THREAD_PRIORITY_HIGHEST);
+ // Unlock the buffer
+#ifdef REFACTOR_ME
+ lpDSBuffer->unlock(lpBuf, _dwBufferSize / 2, NULL, NULL);
+#endif
- /* Start to play the buffer */
- lpDSBuffer->SetCurrentPosition(0);
- bIsPlaying = true;
+ // Create a thread to play the stream
+ _hThreadEnd = CoroScheduler.createEvent(false, false);
+ _hPlayThread = CoroScheduler.createProcess(playThread, this, sizeof(FPStream *));
+
+ // Start to play the buffer
+#ifdef REFACTOR_ME
+ lpDSBuffer->setCurrentPosition(0);
+#endif
+ _bIsPlaying = true;
- dspnHot[0].dwOffset = 32;
- dspnHot[0].hEventNotify = hHot1;
+#ifdef REFACTOR_ME
+ _dspnHot[0].dwOffset = 32;
+ _dspnHot[0].hEventNotify = _hHot1;
- dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
- dspnHot[1].hEventNotify = hHot2;
+ _dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
+ _dspnHot[1].hEventNotify = _hHot2;
- dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
- dspnHot[2].hEventNotify = hHot3;
+ _dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
+ _dspnHot[2].hEventNotify = _hHot3;
if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) {
int a = 1;
@@ -748,11 +1124,11 @@ bool FPStream::play() {
switch (dwCodec) {
case FPCODEC_RAW:
- lpCodec = new CODECRAW(bLoop);
+ _codec = new CODECRAW(_bLoop);
break;
case FPCODEC_ADPCM:
- lpCodec = new CODECADPCMSTEREO(bLoop);
+ _codec = new CODECADPCMSTEREO(_bLoop);
break;
default:
@@ -770,7 +1146,7 @@ bool FPStream::play() {
}
/* Uncompress the data from the stream directly into the locked buffer */
- lpCodec->Decompress(hFile, lpBuf, dwBufferSize / 2);
+ _codec->Decompress(hFile, lpBuf, dwBufferSize / 2);
/* Unlock the buffer */
lpDSBuffer->Unlock(lpBuf, dwBufferSize / 2, NULL, NULL);
@@ -846,7 +1222,7 @@ bool FPStream::stop(bool bSync) {
GlobalFree(lpTempBuffer);
/* Close and free the CODEC */
- delete lpCodec;
+ delete _codec;
bIsPlaying = false;
bPaused = false;
@@ -882,7 +1258,7 @@ void FPStream::waitForSync(FPStream *toplay) {
GlobalFree(lpTempBuffer);
/* Close and free the CODEC */
- delete lpCodec;
+ delete _codec;
#endif
_bIsPlaying = false;
}
@@ -892,129 +1268,110 @@ void FPStream::waitForSync(FPStream *toplay) {
*
*/
-void FPStream::playThread(FPStream *This) {
-#ifdef REFACTOR_ME
- byte *lpLockBuf;
- uint32 dwResult;
- byte *lpLockBuf2;
- uint32 dwResult2;
- bool cicla = true;
- uint32 countEnd;
- bool bPrecache;
- char buf[1024];
+void FPStream::playThread(CORO_PARAM, const void *param) {
+ CORO_BEGIN_CONTEXT;
+ byte *lpLockBuf;
+ uint32 dwResult;
+ byte *lpLockBuf2;
+ uint32 dwResult2;
+ bool cicla;
+ uint32 countEnd;
+ bool bPrecache;
+ char buf[1024];
+ uint32 hList[5];
+ CORO_END_CONTEXT(_ctx);
- /* Events that signal when you need to do something */
- HANDLE hList[5] = { This->hThreadEnd, This->hHot1, This->hHot2, This->hHot3, This->hPlayThread_PlayFast };
+// FPStream *This = *(FPStream **)param;
- bPrecache = true;
- countEnd = 0;
- while (cicla) {
- if (This->lpCodec->EndOfStream() && This->lpCodec->bLoop == false) {
- countEnd++;
- if (countEnd == 3)
+ CORO_BEGIN_CODE(_ctx);
+#ifdef REFACTOR_ME
+ // Events that signal when you need to do something
+ _ctx->hList[0] = This->_hThreadEnd;
+ _ctx->hList[1] = This->_hHot1;
+ _ctx->hList[2] = This->_hHot2;
+ _ctx->hList[3] = This->_hHot3;
+ _ctx->hList[4] = This->_hPlayThreadPlayFast;
+
+ _ctx->cicla = true;
+ _ctx->bPrecache = true;
+ _ctx->countEnd = 0;
+ while (_ctx->cicla) {
+ if (This->_codec->endOfStream() && This->_codec->_bLoop == false) {
+ _ctx->countEnd++;
+ if (_ctx->countEnd == 3)
break;
}
- /* Uncompresses the data being written into the temporary buffer */
- if (This->lastVolume == 0)
- ZeroMemory(This->lpTempBuffer, This->dwBufferSize / 2);
- else if (bPrecache)
- This->lpCodec->Decompress(This->_file, This->lpTempBuffer, This->dwBufferSize / 2);
+ // Uncompresses the data being written into the temporary buffer
+ if (This->_lastVolume == 0)
+ ZeroMemory(This->_lpTempBuffer, This->_dwBufferSize / 2);
+ else if (_ctx->bPrecache)
+ This->_codec->decompress(This->_file.readStream(This->_file.size()), This->_lpTempBuffer, This->_dwBufferSize / 2);
+
+ _ctx->bPrecache = false;
- bPrecache = false;
+ // Waits for an event. Since they are all in automatic reset, there is no need to reset it after
- /* Waits for an event. Since they are all in automatic reset, there is no need to reset it after */
+ uint32 dwBufStatus;
-// uint32 dwBufStatus;
-// This->lpDSBuffer->GetStatus(&dwBufStatus);
+ CORO_INVOKE_4(CoroScheduler.waitForMultipleObjects, 5, _ctx->hList, false, CORO_INFINITE, &_ctx->dwResult);
+ // Check to determine which event has been set
+ if (CoroScheduler.getEvent(This->_hThreadEnd)->signalled) {
+ /* Must leave the thread */
+ _ctx->cicla = false;
+
+ } else if (CoroScheduler.getEvent(This->_hHot1)->signalled) {
+ // Must fill the second half of the buffer
+ This->lpDSBuffer->Lock(This->_dwBufferSize / 2, This->_dwBufferSize / 2, (void **)&_ctx->lpLockBuf, &_ctx->dwResult, (void **)&_ctx->lpLockBuf2, &_ctx->dwResult2, 0);
-// sprintf(buf, "WFMO: %x (buf status: %x) MyThread: 0x%x\n", This->lpDSBuffer, dwBufStatus, GetCurrentThreadId());
-// warning(buf);
- dwResult = WaitForMultipleObjects(5, hList, false, CORO_INFINITE);
+ copyMemory(_ctx->lpLockBuf, This->_lpTempBuffer, This->_dwBufferSize / 2);
+ This->lpDSBuffer->Unlock(_ctx->lpLockBuf, This->_dwBufferSize / 2, _ctx->lpLockBuf2, 0);
- /* uint32 dwPlay, dwWrite;
- This->lpDSBuffer->GetCurrentPosition(&dwPlay, &dwWrite);
- sprintf(buf, "CP Play: %u, Write: %u\n", dwPlay, dwWrite);
- warning(buf); */
+ _ctx->bPrecache = true;
- /* Make a switch to determine which event has been set */
- switch (dwResult - WAIT_OBJECT_0) {
- case 0:
- /* Must leave the thread */
- cicla = false;
- break;
-
- case 1:
- /* Must fill the second half of the buffer */
-// if (dwPlay >= This->dspnHot[0].dwOffset && dwPlay <= This->dspnHot[0].dwOffset+1024 )
- {
-// sprintf(buf, "Prima metà buffer: %x\n", This->lpDSBuffer);
-// warning(buf);
- This->lpDSBuffer->Lock(This->dwBufferSize / 2, This->dwBufferSize / 2, (void **)&lpLockBuf, &dwResult, (void **)&lpLockBuf2, &dwResult2, 0);
- // sprintf(buf, "LockedBuf: dwResult=%x, dwBufferSize/2=%x, lpLockBuf2=%x, dwResult2=%x\n", dwResult, This->dwBufferSize/2, lpLockBuf2, dwResult2);
- // warning(buf);
- copyMemory(lpLockBuf, This->lpTempBuffer, This->dwBufferSize / 2);
- This->lpDSBuffer->Unlock(lpLockBuf, This->dwBufferSize / 2, lpLockBuf2, 0);
- bPrecache = true;
- }
- break;
+ } else if (CoroScheduler.getEvent(This->_hHot2)->signalled) {
+ This->lpDSBuffer->Lock(0, This->_dwBufferSize / 2, (void **)&_ctx->lpLockBuf, &_ctx->dwResult, NULL, NULL, 0);
- case 2:
- /* Must fill the first half of the buffer */
-// if (dwPlay >= This->dspnHot[1].dwOffset && dwPlay <= This->dspnHot[1].dwOffset+1024 )
- {
-// sprintf(buf, "Seconda metà buffer: %x\n", This->lpDSBuffer);
-// warning(buf);
- This->lpDSBuffer->Lock(0, This->dwBufferSize / 2, (void **)&lpLockBuf, &dwResult, NULL, NULL, 0);
- copyMemory(lpLockBuf, This->lpTempBuffer, This->dwBufferSize / 2);
- This->lpDSBuffer->Unlock(lpLockBuf, This->dwBufferSize / 2, NULL, NULL);
- bPrecache = true;
- }
- break;
+ copyMemory(_ctx->lpLockBuf, This->_lpTempBuffer, This->_dwBufferSize / 2);
+ This->lpDSBuffer->Unlock(_ctx->lpLockBuf, This->_dwBufferSize / 2, NULL, NULL);
+
+ _ctx->bPrecache = true;
+
+ } else if (CoroScheduler.getEvent(This->_hHot3)->signalled) {
+
+ if (This->_bSyncExit) {
+ CoroScheduler.setEvent(This->_syncToPlay->_hPlayThreadPlayFast);
- case 3: {
-// sprintf(buf, "End of buffer %x (SyncToPlay [%x]=%x, SyncExit: [%x]=%d)\n", This->lpDSBuffer, &This->SyncToPlay, This->SyncToPlay, &This->bSyncExit, This->bSyncExit);
-// warning(buf);
- if (This->bSyncExit) {
-// sprintf(buf, "Go with sync (Buffer: %x) MyThread: %x!\n", This->SyncToPlay->lpDSBuffer, GetCurrentThreadId());
-// warning(buf);
- //This->SyncToPlay->PlayFast();
- SetEvent(This->SyncToPlay->hPlayThread_PlayFast);
// Transfer immediatly control to the other threads
- Sleep(0);
- This->bSyncExit = false;
- cicla = false;
+ CORO_SLEEP(1);
+
+ This->_bSyncExit = false;
+ _ctx->cicla = false;
break;
}
- }
- break;
-
- case 4:
- This->PlayFast();
- break;
+ } else if (CoroScheduler.getEvent(This->_hPlayThreadPlayFast)->signalled) {
+ This->playFast();
}
}
- /* Close the DirectSound buffer */
-// sprintf(buf, "Exiting thread. Buffer = %x, MyThread = 0x%x\n", This->lpDSBuffer, GetCurrentThreadId());
-// warning(buf);
+ // Close the DirectSound buffer
This->lpDSBuffer->Stop();
-
- ExitThread(0);
#endif
+
+ CORO_END_CODE;
}
+
/**
* Unables or disables stream loop.
*
- * @param bLoop True enable loop, False disables it
+ * @param _bLoop True enable loop, False disables it
*
* @remarks The loop must be activated BEFORE the stream starts
* playing. Any changes made during the play will have no
* effect until the stream is stopped then played again.
*/
-
void FPStream::setLoop(bool loop) {
_bLoop = loop;
}
@@ -1025,38 +1382,38 @@ void FPStream::setLoop(bool loop) {
*
* @param bPause True enables pause, False disables it
*/
-
void FPStream::pause(bool bPause) {
+ if (_bFileLoaded) {
+ if (bPause && _bIsPlaying) {
#ifdef REFACTOR_ME
+ _lpDSBuffer->Stop();
+#endif
+ _bIsPlaying = false;
+ _bPaused = true;
+ } else if (!bPause && _bPaused) {
+#ifdef REFACTOR_ME
+ _dspnHot[0].dwOffset = 32;
+ _dspnHot[0].hEventNotify = hHot1;
- if (bFileLoaded) {
- if (bPause && bIsPlaying) {
- lpDSBuffer->Stop();
- bIsPlaying = false;
- bPaused = true;
- } else if (!bPause && bPaused) {
- dspnHot[0].dwOffset = 32;
- dspnHot[0].hEventNotify = hHot1;
-
- dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
- dspnHot[1].hEventNotify = hHot2;
+ _dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
+ _dspnHot[1].hEventNotify = hHot2;
- dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
- dspnHot[2].hEventNotify = hHot3;
+ _dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
+ _dspnHot[2].hEventNotify = hHot3;
if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) {
int a = 1;
}
- lpDSBuffer->Play(0, 0, bLoop);
- bIsPlaying = true;
- bPaused = false;
+ lpDSBuffer->Play(0, 0, _bLoop);
+#endif
+ _bIsPlaying = true;
+ _bPaused = false;
// Trick to reset the volume after a possible new sound configuration
- SetVolume(lastVolume);
+ setVolume(_lastVolume);
}
}
-#endif
}
/**
diff --git a/engines/tony/sound.h b/engines/tony/sound.h
index 4dd00a3028..38ce6de2a7 100644
--- a/engines/tony/sound.h
+++ b/engines/tony/sound.h
@@ -245,6 +245,24 @@ public:
bool endOfBuffer() const;
};
+/**
+ * Codec base class
+ */
+class CODEC {
+protected:
+ bool _bEndReached;
+
+public:
+ bool _bLoop;
+
+ CODEC(bool _bLoop = true);
+ virtual ~CODEC();
+ virtual uint32 decompress(Common::SeekableReadStream *stream, void *lpBuf, uint32 dwSize) = 0;
+ virtual void loopReset() = 0;
+ bool endOfStream();
+};
+
+
class FPStream {
private:
// HWND hwnd;
@@ -258,12 +276,12 @@ private:
uint32 _dwSize; // Stream size (bytes)
uint32 _dwCodec; // CODEC used
- HANDLE _hThreadEnd; // Event used to close thread
+ uint32 _hThreadEnd; // Event used to close thread
Common::File _file; // File handle used for the stream
- HANDLE _hPlayThread; // Handle of the Play thread
- HANDLE _hHot1, _hHot2, _hHot3; // Events set by DirectSoundNotify
- HANDLE _hPlayThreadPlayFast;
- HANDLE _hPlayThreadPlayNormal;
+ uint32 _hPlayThread; // Handle of the Play thread
+ uint32 _hHot1, _hHot2, _hHot3; // Events set by DirectSoundNotify
+ uint32 _hPlayThreadPlayFast;
+ uint32 _hPlayThreadPlayNormal;
bool _bSoundSupported; // True if the sound is active
bool _bFileLoaded; // True if the file is open
@@ -273,6 +291,7 @@ private:
bool _bPaused;
int _lastVolume;
FPStream *_syncToPlay;
+ CODEC *_codec;
// DSBPOSITIONNOTIFY dspnHot[3];
@@ -286,7 +305,7 @@ private:
* Thread playing the stream
*
*/
- static void playThread(FPStream *This);
+ static void playThread(CORO_PARAM, const void *param);
public:
@@ -321,13 +340,13 @@ public:
/**
* Opens a file stream
*
- * @param lpszFile Filename to be opened
+ * @param fileName Filename to be opened
* @param dwCodec CODEC to be used to uncompress samples
*
* @returns True is everything is OK, False otherwise
*/
- bool loadFile(const char *lpszFileName, uint32 dwCodec = FPCODEC_RAW, int nSync = 2000);
+ bool loadFile(const Common::String &fileName, uint32 dwCodec = FPCODEC_RAW, int nSync = 2000);
/**
* Closes a file stream (opened or not).
diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp
index 9e9e032e49..2c102f5c8b 100644
--- a/engines/tony/tony.cpp
+++ b/engines/tony/tony.cpp
@@ -187,10 +187,7 @@ void TonyEngine::GUIError(const Common::String &msg) {
GUIErrorMessage(msg);
}
-void TonyEngine::playMusic(int nChannel, const char *fn, int nFX, bool bLoop, int nSync) {
- warning("TODO: TonyEngine::playMusic");
-// g_system->lockMutex(csMusic);
-
+void TonyEngine::playMusic(int nChannel, const Common::String &fname, int nFX, bool bLoop, int nSync) {
if (nChannel < 4)
if (GLOBALS._flipflop)
nChannel = nChannel + 1;
@@ -207,64 +204,78 @@ void TonyEngine::playMusic(int nChannel, const char *fn, int nFX, bool bLoop, in
break;
}
-#ifdef REFACTOR_ME
- // Mette il path giusto
- if (nChannel < 4)
- GetDataDirectory(DD_MUSIC, path_buffer);
- else
- GetDataDirectory(DD_LAYER, path_buffer);
- _splitpath(path_buffer, drive, dir, NULL, NULL);
- _splitpath(fn, NULL, NULL, fname, ext);
- _makepath(path_buffer, drive, dir, fname, ext);
-
- _makepath(path_buffer, drive, dir, fname, ext);
-
if (nFX == 22) { // Sync a tempo
- curChannel = nChannel;
- strcpy(nextMusic, path_buffer);
- nextLoop = bLoop;
- nextSync = nSync;
- if (flipflop)
- nextChannel = nChannel - 1;
+ GLOBALS._curChannel = nChannel;
+ GLOBALS._nextLoop = bLoop;
+ GLOBALS._nextSync = nSync;
+ if (GLOBALS._flipflop)
+ GLOBALS._nextChannel = nChannel - 1;
else
- nextChannel = nChannel + 1;
- DWORD id;
- HANDLE hThread = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)DoNextMusic, _stream, 0, &id);
- SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
+ GLOBALS._nextChannel = nChannel + 1;
+
+ uint32 hThread = CoroScheduler.createProcess(doNextMusic, &_stream, sizeof(FPStream ***));
+ assert(hThread != CORO_INVALID_PID_VALUE);
+
} else if (nFX == 44) { // Cambia canale e lascia finire il primo
- if (flipflop)
- nextChannel = nChannel - 1;
+ if (GLOBALS._flipflop)
+ GLOBALS._nextChannel = nChannel - 1;
else
- nextChannel = nChannel + 1;
+ GLOBALS._nextChannel = nChannel + 1;
- _stream[nextChannel]->Stop();
- _stream[nextChannel]->UnloadFile();
+ _stream[GLOBALS._nextChannel]->stop();
+ _stream[GLOBALS._nextChannel]->unloadFile();
if (!getIsDemo()) {
- if (!_stream[nextChannel]->LoadFile(path_buffer, FPCODEC_ADPCM, nSync))
- theGame.Abort();
+ if (!_stream[GLOBALS._nextChannel]->loadFile(fname, FPCODEC_ADPCM, nSync))
+ _vm->abortGame();
} else {
- _stream[nextChannel]->LoadFile(path_buffer, FPCODEC_ADPCM, nSync);
+ _stream[GLOBALS._nextChannel]->loadFile(fname, FPCODEC_ADPCM, nSync);
}
- _stream[nextChannel]->SetLoop(bLoop);
- _stream[nextChannel]->Play();
+ _stream[GLOBALS._nextChannel]->setLoop(bLoop);
+ _stream[GLOBALS._nextChannel]->play();
- flipflop = 1 - flipflop;
+ GLOBALS._flipflop = 1 - GLOBALS._flipflop;
} else {
if (!getIsDemo()) {
- if (!_stream[nChannel]->LoadFile(path_buffer, FPCODEC_ADPCM, nSync))
- theGame.Abort();
+ if (!_stream[nChannel]->loadFile(fname, FPCODEC_ADPCM, nSync))
+ _vm->abortGame();
} else {
- _stream[nChannel]->LoadFile(path_buffer, FPCODEC_ADPCM, nSync);
+ _stream[nChannel]->loadFile(fname, FPCODEC_ADPCM, nSync);
}
- _stream[nChannel]->SetLoop(bLoop);
- _stream[nChannel]->Play();
+ _stream[nChannel]->setLoop(bLoop);
+ _stream[nChannel]->play();
}
-#endif
+}
-// g_system->unlockMutex(csMusic);
+void TonyEngine::doNextMusic(CORO_PARAM, const void *param) {
+ CORO_BEGIN_CONTEXT;
+ Common::String fn;
+ CORO_END_CONTEXT(_ctx);
+
+ FPStream **streams = *(FPStream ***)param;
+
+ CORO_BEGIN_CODE(_ctx);
+
+ if (!_vm->getIsDemo()) {
+ if (!streams[GLOBALS._nextChannel]->loadFile(GLOBALS._nextMusic, FPCODEC_ADPCM, GLOBALS._nextSync))
+ _vm->abortGame();
+ } else {
+ streams[GLOBALS._nextChannel]->loadFile(GLOBALS._nextMusic, FPCODEC_ADPCM, GLOBALS._nextSync);
+ }
+
+ streams[GLOBALS._nextChannel]->setLoop(GLOBALS._nextLoop);
+ streams[GLOBALS._nextChannel]->prefetch();
+
+ streams[GLOBALS._curChannel]->stop(true);
+ streams[GLOBALS._curChannel]->waitForSync(streams[GLOBALS._nextChannel]);
+
+ streams[GLOBALS._curChannel]->unloadFile();
+
+ GLOBALS._flipflop = 1 - GLOBALS._flipflop;
+
+ CORO_END_CODE;
}
void TonyEngine::playSFX(int nChannel, int nFX) {
diff --git a/engines/tony/tony.h b/engines/tony/tony.h
index 5f6fd8cb44..94dc3de92d 100644
--- a/engines/tony/tony.h
+++ b/engines/tony/tony.h
@@ -87,6 +87,8 @@ private:
void closeVoiceDatabase();
void initCustomFunctionMap();
static void playProcess(CORO_PARAM, const void *param);
+ static void doNextMusic(CORO_PARAM, const void *param);
+
protected:
// Engine APIs
virtual Common::Error run();
@@ -183,7 +185,7 @@ public:
// Music
// ******
- void playMusic(int nChannel, const char *fn, int nFX, bool bLoop, int nSync);
+ void playMusic(int nChannel, const Common::String &fn, int nFX, bool bLoop, int nSync);
void stopMusic(int nChannel);
void playSFX(int nSfx, int nFX = 0);