2001-12-01 17:23:50 +00:00
/* ScummVM - Scumm Interpreter
2002-03-20 17:51:07 +00:00
* Copyright ( C ) 2001 Ludvig Strigeus
2003-03-06 21:46:56 +00:00
* Copyright ( C ) 2001 - 2003 The ScummVM project
2001-12-01 17:23:50 +00:00
*
* 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 .
2003-08-01 20:39:16 +00:00
2001-12-01 17:23:50 +00:00
* 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 .
2003-08-01 20:39:16 +00:00
2001-12-01 17:23:50 +00:00
* 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 . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*
* $ Header $
2003-08-01 20:39:16 +00:00
*
2001-12-01 17:23:50 +00:00
*/
# include "stdafx.h"
2003-08-05 23:58:24 +00:00
2003-06-15 01:42:19 +00:00
# include "common/util.h"
# include "common/gameDetector.h" // For kDefaultMasterVolume etc.
2001-12-01 17:23:50 +00:00
2003-08-05 23:58:24 +00:00
# include "scumm/imuse.h"
# include "scumm/imuse_internal.h"
# include "scumm/instrument.h"
# include "scumm/saveload.h"
# include "scumm/scumm.h"
# include "sound/mididrv.h"
2001-12-01 17:23:50 +00:00
2002-12-15 01:55:27 +00:00
////////////////////////////////////////
//
// IMuseInternal implementation
//
////////////////////////////////////////
2001-12-01 17:23:50 +00:00
2003-05-23 04:19:47 +00:00
IMuseInternal : : IMuseInternal ( ) :
2003-08-01 20:39:16 +00:00
_old_adlib_instruments ( false ) ,
_enable_multi_midi ( false ) ,
_midi_adlib ( 0 ) ,
_midi_native ( 0 ) ,
_base_sounds ( 0 ) ,
_paused ( false ) ,
_initialized ( false ) ,
_tempoFactor ( 0 ) ,
_player_limit ( ARRAYSIZE ( _players ) ) ,
_recycle_players ( false ) ,
_queue_end ( 0 ) ,
_queue_pos ( 0 ) ,
_queue_sound ( 0 ) ,
_queue_adding ( 0 ) ,
_queue_marker ( 0 ) ,
_queue_cleared ( 0 ) ,
_master_volume ( 0 ) ,
_music_volume ( 0 ) ,
_trigger_count ( 0 ) ,
_snm_trigger_index ( 0 )
2003-05-23 04:19:47 +00:00
{
2003-08-01 20:39:16 +00:00
memset ( _channel_volume , 0 , sizeof ( _channel_volume ) ) ;
memset ( _channel_volume_eff , 0 , sizeof ( _channel_volume_eff ) ) ;
memset ( _volchan_table , 0 , sizeof ( _volchan_table ) ) ;
memset ( _active_notes , 0 , sizeof ( _active_notes ) ) ;
2003-05-23 04:19:47 +00:00
}
2002-10-21 07:31:51 +00:00
IMuseInternal : : ~ IMuseInternal ( ) {
terminate ( ) ;
}
2003-05-19 05:04:38 +00:00
MidiDriver * IMuseInternal : : getMidiDriver ( ) {
MidiDriver * driver = NULL ;
if ( _midi_native ) {
driver = _midi_native ;
} else {
// Route it through Adlib anyway.
if ( ! _midi_adlib ) {
2003-08-05 23:58:24 +00:00
_midi_adlib = MidiDriver_ADLIB_create ( _mixer ) ;
2003-08-01 20:39:16 +00:00
initMidiDriver ( _midi_adlib ) ;
2003-05-19 05:04:38 +00:00
}
driver = _midi_adlib ;
}
return driver ;
}
2003-08-01 20:39:16 +00:00
byte * IMuseInternal : : findStartOfSound ( int sound ) {
2002-03-14 08:04:21 +00:00
byte * ptr = NULL ;
2002-04-11 17:19:16 +00:00
int32 size , pos ;
2001-12-01 17:23:50 +00:00
2002-12-18 13:22:40 +00:00
if ( _base_sounds )
2002-04-11 17:19:16 +00:00
ptr = _base_sounds [ sound ] ;
2002-03-14 08:04:21 +00:00
2002-04-11 17:19:16 +00:00
if ( ptr = = NULL ) {
2003-08-01 20:39:16 +00:00
debug ( 1 , " IMuseInternal::findStartOfSound(): Sound %d doesn't exist! " , sound ) ;
2002-04-24 14:13:09 +00:00
return NULL ;
2001-12-01 17:23:50 +00:00
}
ptr + = 8 ;
2003-06-14 18:52:30 +00:00
size = READ_BE_UINT32 ( ptr ) ;
2001-12-01 17:23:50 +00:00
ptr + = 4 ;
2003-05-23 18:35:53 +00:00
// Okay, we're looking for one of those things: either
2003-08-01 20:39:16 +00:00
// an 'MThd' tag(for SMF), or a 'FORM' tag(for XMIDI).
2003-05-23 18:35:53 +00:00
size = 48 ; // Arbitrary; we should find our tag within the first 48 bytes of the resource
2001-12-01 17:23:50 +00:00
pos = 0 ;
while ( pos < size ) {
2003-08-01 20:39:16 +00:00
if ( ! memcmp ( ptr + pos , " MThd " , 4 ) | | ! memcmp ( ptr + pos , " FORM " , 4 ) )
2003-05-23 18:35:53 +00:00
return ptr + pos ;
+ + pos ; // We could probably iterate more intelligently
2001-12-01 17:23:50 +00:00
}
2002-07-07 18:04:03 +00:00
2003-05-23 18:35:53 +00:00
debug ( 3 , " IMuseInternal::findStartOfSound(): Failed to align on sound %d! " , sound ) ;
return 0 ;
2002-05-04 00:20:39 +00:00
}
2003-03-06 17:58:13 +00:00
bool IMuseInternal : : isMT32 ( int sound ) {
2002-05-04 00:20:39 +00:00
byte * ptr = NULL ;
uint32 tag ;
if ( _base_sounds )
ptr = _base_sounds [ sound ] ;
if ( ptr = = NULL )
return false ;
2001-12-01 17:23:50 +00:00
2002-07-07 18:04:03 +00:00
tag = * ( ( ( uint32 * ) ptr ) + 1 ) ;
2002-05-04 00:20:39 +00:00
switch ( tag ) {
case MKID ( ' ADL ' ) :
return false ;
2003-05-28 11:56:50 +00:00
case MKID ( ' AMI ' ) :
return true ;
2002-05-04 00:20:39 +00:00
case MKID ( ' ROL ' ) :
return true ;
case MKID ( ' GMD ' ) :
return false ;
case MKID ( ' MAC ' ) :
return true ;
case MKID ( ' SPK ' ) :
return false ;
}
2002-07-07 18:04:03 +00:00
2002-05-04 00:20:39 +00:00
return false ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
bool IMuseInternal : : isGM ( int sound ) {
2002-09-29 11:11:42 +00:00
byte * ptr = NULL ;
uint32 tag ;
if ( _base_sounds )
ptr = _base_sounds [ sound ] ;
if ( ptr = = NULL )
return false ;
tag = * ( ( ( uint32 * ) ptr ) + 1 ) ;
switch ( tag ) {
case MKID ( ' ADL ' ) :
return false ;
2003-05-28 11:56:50 +00:00
case MKID ( ' AMI ' ) :
return true ; // Yeah... for our purposes, this is GM
2002-09-29 11:11:42 +00:00
case MKID ( ' ROL ' ) :
return true ; // Yeah... for our purposes, this is GM
case MKID ( ' GMD ' ) :
return true ;
case MKID ( ' MIDI ' ) :
return true ;
case MKID ( ' MAC ' ) :
return true ; // I guess this one too, since it qualifies under isMT32()
case MKID ( ' SPK ' ) :
return false ;
}
return false ;
}
2003-08-01 20:39:16 +00:00
MidiDriver * IMuseInternal : : getBestMidiDriver ( int sound ) {
2003-05-16 22:00:33 +00:00
MidiDriver * driver = NULL ;
2003-08-01 20:39:16 +00:00
if ( isGM ( sound ) ) {
2003-05-16 22:00:33 +00:00
if ( _midi_native ) {
driver = _midi_native ;
} else {
// Route it through Adlib anyway.
if ( ! _midi_adlib ) {
2003-08-05 23:58:24 +00:00
_midi_adlib = MidiDriver_ADLIB_create ( _mixer ) ;
2003-08-01 20:39:16 +00:00
initMidiDriver ( _midi_adlib ) ;
2003-05-16 22:00:33 +00:00
}
driver = _midi_adlib ;
}
} else {
2003-08-01 20:39:16 +00:00
if ( ! _midi_adlib & & ( _enable_multi_midi | | ! _midi_native ) ) {
2003-08-05 23:58:24 +00:00
_midi_adlib = MidiDriver_ADLIB_create ( _mixer ) ;
2003-08-01 20:39:16 +00:00
initMidiDriver ( _midi_adlib ) ;
2003-05-16 22:00:33 +00:00
}
driver = _midi_adlib ;
}
return driver ;
}
2003-03-18 16:13:52 +00:00
bool IMuseInternal : : startSound ( int sound ) {
2001-12-01 17:23:50 +00:00
Player * player ;
void * mdhd ;
2002-12-14 02:51:37 +00:00
// Do not start a sound if it is already set to
// start on an ImTrigger event. This fixes carnival
// music problems where a sound has been set to trigger
// at the right time, but then is started up immediately
// anyway, only to be restarted later when the trigger
// occurs.
int i ;
ImTrigger * trigger = _snm_triggers ;
2003-08-01 20:39:16 +00:00
for ( i = ARRAYSIZE ( _snm_triggers ) ; i ; - - i , + + trigger ) {
2002-12-14 02:51:37 +00:00
if ( trigger - > sound & & trigger - > id & & trigger - > command [ 0 ] = = 8 & & trigger - > command [ 1 ] = = sound )
return false ;
}
2003-05-23 18:35:53 +00:00
// Not sure exactly what the old code was doing,
// but we'll go ahead and do a similar check.
2003-08-01 20:39:16 +00:00
mdhd = findStartOfSound ( sound ) ;
2003-05-23 18:35:53 +00:00
if ( ! mdhd ) {
2003-08-01 20:39:16 +00:00
debug ( 2 , " IMuseInternal::startSound(): Couldn't find sound %d! " , sound ) ;
2003-05-23 18:35:53 +00:00
return false ;
}
/*
2002-04-11 17:19:16 +00:00
mdhd = findTag ( sound , MDHD_TAG , 0 ) ;
if ( ! mdhd ) {
2002-03-11 04:37:06 +00:00
mdhd = findTag ( sound , MDPG_TAG , 0 ) ;
if ( ! mdhd ) {
2003-08-01 20:39:16 +00:00
debug ( 2 , " SE::startSound failed: Couldn't find sound %d " , sound ) ;
2002-09-30 06:04:50 +00:00
return false ;
2002-03-11 04:37:06 +00:00
}
2002-03-05 16:13:09 +00:00
}
2003-05-23 18:35:53 +00:00
*/
2002-04-11 17:19:16 +00:00
2003-05-16 22:00:33 +00:00
// Check which MIDI driver this track should use.
// If it's NULL, it ain't something we can play.
2003-08-01 20:39:16 +00:00
MidiDriver * driver = getBestMidiDriver ( sound ) ;
2003-05-16 22:00:33 +00:00
if ( ! driver )
return false ;
2002-10-21 08:17:18 +00:00
// If the requested sound is already playing, start it over
// from scratch. This was originally a hack to prevent Sam & Max
// iMuse messiness while upgrading the iMuse engine, but it
// is apparently necessary to deal with fade-and-restart
// race conditions that were observed in MI2. Reference
2003-08-01 20:39:16 +00:00
// Bug #590511 and Patch #607175(which was reversed to fix
2002-10-21 08:17:18 +00:00
// an FOA regression: Bug #622606).
2003-08-01 20:39:16 +00:00
player = findActivePlayer ( sound ) ;
2003-05-23 04:19:47 +00:00
if ( ! player )
2002-10-14 16:42:57 +00:00
player = allocate_player ( 128 ) ;
if ( ! player )
return false ;
2001-12-01 17:23:50 +00:00
player - > clear ( ) ;
2003-08-01 20:39:16 +00:00
return player - > startSound ( sound , driver ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
Player * IMuseInternal : : allocate_player ( byte priority ) {
2001-12-01 17:23:50 +00:00
Player * player = _players , * best = NULL ;
int i ;
byte bestpri = 255 ;
2003-05-23 18:35:53 +00:00
for ( i = _player_limit ; i ! = 0 ; i - - , player + + ) {
2003-05-23 04:19:47 +00:00
if ( ! player - > isActive ( ) )
2001-12-01 17:23:50 +00:00
return player ;
2003-05-23 04:19:47 +00:00
if ( player - > getPriority ( ) < bestpri ) {
2001-12-01 17:23:50 +00:00
best = player ;
2003-05-23 04:19:47 +00:00
bestpri = player - > getPriority ( ) ;
2001-12-01 17:23:50 +00:00
}
}
2003-05-23 18:35:53 +00:00
if ( bestpri < priority | | _recycle_players )
2001-12-01 17:23:50 +00:00
return best ;
debug ( 1 , " Denying player request " ) ;
return NULL ;
}
2003-03-06 17:58:13 +00:00
void IMuseInternal : : init_players ( ) {
2001-12-01 17:23:50 +00:00
Player * player = _players ;
int i ;
2002-04-11 17:19:16 +00:00
for ( i = ARRAYSIZE ( _players ) ; i ! = 0 ; i - - , player + + ) {
player - > _se = this ;
2003-07-07 05:45:55 +00:00
player - > clear ( ) ; // Used to just set _active to false
2001-12-01 17:23:50 +00:00
}
}
2003-03-06 17:58:13 +00:00
void IMuseInternal : : init_parts ( ) {
2001-12-01 17:23:50 +00:00
Part * part ;
int i ;
2002-04-11 17:19:16 +00:00
for ( i = 0 , part = _parts ; i ! = ARRAYSIZE ( _parts ) ; i + + , part + + ) {
2003-05-16 01:52:45 +00:00
part - > init ( ) ;
2001-12-01 17:23:50 +00:00
part - > _slot = i ;
}
}
2003-03-18 16:13:52 +00:00
int IMuseInternal : : stopSound ( int sound ) {
2001-12-01 17:23:50 +00:00
int r = - 1 ;
2003-08-01 20:39:16 +00:00
Player * player = findActivePlayer ( sound ) ;
2003-05-23 04:19:47 +00:00
if ( player ) {
player - > clear ( ) ;
r = 0 ;
2001-12-01 17:23:50 +00:00
}
return r ;
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : stop_all_sounds ( ) {
2001-12-01 17:23:50 +00:00
Player * player = _players ;
int i ;
2002-04-11 17:19:16 +00:00
for ( i = ARRAYSIZE ( _players ) ; i ! = 0 ; i - - , player + + ) {
2003-05-23 04:19:47 +00:00
if ( player - > isActive ( ) )
2001-12-01 17:23:50 +00:00
player - > clear ( ) ;
}
return 0 ;
}
2003-08-01 20:39:16 +00:00
void IMuseInternal : : on_timer ( MidiDriver * midi ) {
2003-05-15 18:24:59 +00:00
if ( _paused )
2001-12-01 17:23:50 +00:00
return ;
2002-04-11 17:19:16 +00:00
2003-05-20 01:12:40 +00:00
if ( midi = = _midi_native | | ! _midi_native )
2003-08-01 20:39:16 +00:00
handleDeferredCommands ( midi ) ;
sequencer_timers ( midi ) ;
2001-12-01 17:23:50 +00:00
}
2003-08-01 20:39:16 +00:00
void IMuseInternal : : sequencer_timers ( MidiDriver * midi ) {
2001-12-01 17:23:50 +00:00
Player * player = _players ;
int i ;
2002-04-11 17:19:16 +00:00
for ( i = ARRAYSIZE ( _players ) ; i ! = 0 ; i - - , player + + ) {
2003-05-23 04:19:47 +00:00
if ( player - > isActive ( ) & & player - > getMidiDriver ( ) = = midi ) {
player - > onTimer ( ) ;
2003-05-15 18:24:59 +00:00
}
2001-12-01 17:23:50 +00:00
}
}
2003-03-06 17:58:13 +00:00
void IMuseInternal : : handle_marker ( uint id , byte data ) {
2003-05-07 22:50:15 +00:00
uint16 * p = 0 ;
2002-04-11 17:19:16 +00:00
uint pos ;
if ( _queue_adding & & _queue_sound = = id & & data = = _queue_marker )
2001-12-01 17:23:50 +00:00
return ;
2003-07-07 05:45:55 +00:00
// Fix for bug #733401, revised for bug #761637:
// It would seem that sometimes a marker is in the queue
// but not at the head position. In the case of our bug,
// this seems to be the result of commands in the queue
// for songs that are no longer playing. So we skip
// ahead to the appropriate marker, effectively chomping
// anything in the queue before it. This fixes the FOA
// end credits music, but needs to be tested for inappopriate
// behavior elsewhere.
2003-05-07 19:24:14 +00:00
pos = _queue_end ;
while ( pos ! = _queue_pos ) {
p = _cmd_queue [ pos ] . array ;
2003-07-07 05:45:55 +00:00
if ( p [ 0 ] = = TRIGGER_ID & & p [ 1 ] = = id & & p [ 2 ] = = data )
2003-05-07 19:24:14 +00:00
break ;
2003-08-01 20:39:16 +00:00
pos = ( pos + 1 ) & ( ARRAYSIZE ( _cmd_queue ) - 1 ) ;
2003-05-07 19:24:14 +00:00
}
if ( pos = = _queue_pos )
return ;
2001-12-01 17:23:50 +00:00
2003-07-07 05:45:55 +00:00
if ( pos ! = _queue_end )
2003-08-01 20:39:16 +00:00
warning ( " Skipping entries in iMuse command queue to reach marker " ) ;
2001-12-01 17:23:50 +00:00
_trigger_count - - ;
_queue_cleared = false ;
do {
2003-08-01 20:39:16 +00:00
pos = ( pos + 1 ) & ( ARRAYSIZE ( _cmd_queue ) - 1 ) ;
2001-12-01 17:23:50 +00:00
if ( _queue_pos = = pos )
break ;
p = _cmd_queue [ pos ] . array ;
if ( * p + + ! = COMMAND_ID )
break ;
_queue_end = pos ;
2003-03-18 16:13:52 +00:00
doCommand ( p [ 0 ] , p [ 1 ] , p [ 2 ] , p [ 3 ] , p [ 4 ] , p [ 5 ] , p [ 6 ] , 0 ) ;
2001-12-01 17:23:50 +00:00
if ( _queue_cleared )
return ;
pos = _queue_end ;
} while ( 1 ) ;
_queue_end = pos ;
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : get_channel_volume ( uint a ) {
2002-04-11 17:19:16 +00:00
if ( a < 8 )
2001-12-01 17:23:50 +00:00
return _channel_volume_eff [ a ] ;
2002-11-17 17:59:00 +00:00
return ( _master_volume * _music_volume / 255 ) > > 1 ;
2001-12-01 17:23:50 +00:00
}
2003-08-01 20:39:16 +00:00
Part * IMuseInternal : : allocate_part ( byte pri , MidiDriver * midi ) {
2002-04-11 17:19:16 +00:00
Part * part , * best = NULL ;
2001-12-01 17:23:50 +00:00
int i ;
2002-04-11 17:19:16 +00:00
for ( i = ARRAYSIZE ( _parts ) , part = _parts ; i ! = 0 ; i - - , part + + ) {
2001-12-01 17:23:50 +00:00
if ( ! part - > _player )
return part ;
if ( pri > = part - > _pri_eff ) {
pri = part - > _pri_eff ;
best = part ;
}
}
2002-12-18 17:14:05 +00:00
if ( best ) {
2001-12-01 17:23:50 +00:00
best - > uninit ( ) ;
2003-08-01 20:39:16 +00:00
reallocateMidiChannels ( midi ) ;
2002-12-18 17:14:05 +00:00
} else {
2001-12-01 17:23:50 +00:00
debug ( 1 , " Denying part request " ) ;
2002-12-18 17:14:05 +00:00
}
2001-12-01 17:23:50 +00:00
return best ;
}
2003-08-01 20:39:16 +00:00
int IMuseInternal : : getSoundStatus ( int sound , bool ignoreFadeouts ) {
2003-05-23 18:35:53 +00:00
Player * player ;
if ( sound = = - 1 ) {
player = _players ;
for ( int i = ARRAYSIZE ( _players ) ; i ; - - i , + + player ) {
2003-08-01 20:39:16 +00:00
if ( player - > isActive ( ) & & ( ! ignoreFadeouts | | ! player - > isFadingOut ( ) ) )
2003-05-24 23:21:08 +00:00
return player - > getID ( ) ;
2003-05-23 18:35:53 +00:00
}
return 0 ;
}
2001-12-01 17:23:50 +00:00
2003-08-01 20:39:16 +00:00
player = findActivePlayer ( sound ) ;
if ( player & & ( ! ignoreFadeouts | | ! player - > isFadingOut ( ) ) )
2003-05-23 04:19:47 +00:00
return 1 ;
2003-05-23 18:35:53 +00:00
return get_queue_sound_status ( sound ) ;
2002-12-05 21:45:55 +00:00
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : get_queue_sound_status ( int sound ) {
2001-12-01 17:23:50 +00:00
uint16 * a ;
2002-04-11 17:19:16 +00:00
int i , j ;
2001-12-01 17:23:50 +00:00
j = _queue_pos ;
i = _queue_end ;
2002-04-11 17:19:16 +00:00
while ( i ! = j ) {
2001-12-01 17:23:50 +00:00
a = _cmd_queue [ i ] . array ;
if ( a [ 0 ] = = COMMAND_ID & & a [ 1 ] = = 8 & & a [ 2 ] = = ( uint16 ) sound )
return 2 ;
2003-08-01 20:39:16 +00:00
i = ( i + 1 ) & ( ARRAYSIZE ( _cmd_queue ) - 1 ) ;
2001-12-01 17:23:50 +00:00
}
return 0 ;
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : set_volchan ( int sound , int volchan ) {
2001-12-01 17:23:50 +00:00
int r ;
int i ;
int num ;
2002-04-11 17:19:16 +00:00
Player * player , * best , * sameid ;
2001-12-01 17:23:50 +00:00
r = get_volchan_entry ( volchan ) ;
2002-04-11 17:19:16 +00:00
if ( r = = - 1 )
2001-12-01 17:23:50 +00:00
return - 1 ;
if ( r > = 8 ) {
2003-08-01 20:39:16 +00:00
player = findActivePlayer ( sound ) ;
2003-05-23 04:19:47 +00:00
if ( player & & player - > _vol_chan ! = ( uint16 ) volchan ) {
player - > _vol_chan = volchan ;
2003-08-01 20:39:16 +00:00
player - > setVolume ( player - > getVolume ( ) ) ;
2003-05-23 04:19:47 +00:00
return 0 ;
2001-12-01 17:23:50 +00:00
}
return - 1 ;
} else {
best = NULL ;
num = 0 ;
sameid = NULL ;
2002-04-11 17:19:16 +00:00
for ( i = ARRAYSIZE ( _players ) , player = _players ; i ! = 0 ; i - - , player + + ) {
2003-05-23 04:19:47 +00:00
if ( player - > isActive ( ) ) {
2002-04-11 17:19:16 +00:00
if ( player - > _vol_chan = = ( uint16 ) volchan ) {
2001-12-01 17:23:50 +00:00
num + + ;
2003-05-23 04:19:47 +00:00
if ( ! best | | player - > getPriority ( ) < = best - > getPriority ( ) )
2001-12-01 17:23:50 +00:00
best = player ;
2003-05-23 04:19:47 +00:00
} else if ( player - > getID ( ) = = ( uint16 ) sound ) {
2001-12-01 17:23:50 +00:00
sameid = player ;
}
}
}
2002-04-11 17:19:16 +00:00
if ( sameid = = NULL )
2001-12-01 17:23:50 +00:00
return - 1 ;
if ( num > = r )
best - > clear ( ) ;
player - > _vol_chan = volchan ;
2003-08-01 20:39:16 +00:00
player - > setVolume ( player - > getVolume ( ) ) ;
2001-12-01 17:23:50 +00:00
return 0 ;
}
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : clear_queue ( ) {
2001-12-01 17:23:50 +00:00
_queue_adding = false ;
_queue_cleared = true ;
_queue_pos = 0 ;
_queue_end = 0 ;
_trigger_count = 0 ;
return 0 ;
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : enqueue_command ( int a , int b , int c , int d , int e , int f , int g ) {
2001-12-01 17:23:50 +00:00
uint16 * p ;
uint i ;
i = _queue_pos ;
if ( i = = _queue_end )
return - 1 ;
2002-04-11 17:19:16 +00:00
if ( a = = - 1 ) {
2001-12-01 17:23:50 +00:00
_queue_adding = false ;
_trigger_count + + ;
return 0 ;
}
p = _cmd_queue [ _queue_pos ] . array ;
p [ 0 ] = COMMAND_ID ;
p [ 1 ] = a ;
p [ 2 ] = b ;
p [ 3 ] = c ;
p [ 4 ] = d ;
p [ 5 ] = e ;
p [ 6 ] = f ;
p [ 7 ] = g ;
2003-08-01 20:39:16 +00:00
i = ( i + 1 ) & ( ARRAYSIZE ( _cmd_queue ) - 1 ) ;
2001-12-01 17:23:50 +00:00
2002-04-11 17:19:16 +00:00
if ( _queue_end ! = i ) {
2001-12-01 17:23:50 +00:00
_queue_pos = i ;
return 0 ;
} else {
2003-08-01 20:39:16 +00:00
_queue_pos = ( i - 1 ) & ( ARRAYSIZE ( _cmd_queue ) - 1 ) ;
2001-12-01 17:23:50 +00:00
return - 1 ;
}
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : query_queue ( int param ) {
2002-04-11 17:19:16 +00:00
switch ( param ) {
2002-12-15 01:55:27 +00:00
case 0 : // Get trigger count
2001-12-01 17:23:50 +00:00
return _trigger_count ;
2002-12-15 01:55:27 +00:00
case 1 : // Get trigger type
2002-04-11 17:19:16 +00:00
if ( _queue_end = = _queue_pos )
2001-12-01 17:23:50 +00:00
return - 1 ;
return _cmd_queue [ _queue_end ] . array [ 1 ] ;
2002-12-15 01:55:27 +00:00
case 2 : // Get trigger sound
2002-04-11 17:19:16 +00:00
if ( _queue_end = = _queue_pos )
2001-12-01 17:23:50 +00:00
return 0xFF ;
return _cmd_queue [ _queue_end ] . array [ 2 ] ;
default :
return - 1 ;
}
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : get_music_volume ( ) {
2002-11-17 17:59:00 +00:00
return _music_volume ;
2002-03-05 23:37:31 +00:00
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : set_music_volume ( uint vol ) {
2002-11-17 17:59:00 +00:00
if ( vol > 255 )
vol = 255 ;
if ( _music_volume = = vol )
return 0 ;
_music_volume = vol ;
vol = vol * _master_volume / 255 ;
2003-08-01 20:39:16 +00:00
for ( uint i = 0 ; i < ARRAYSIZE ( _channel_volume ) ; i + + ) {
2002-11-17 17:59:00 +00:00
_channel_volume_eff [ i ] = _channel_volume [ i ] * vol / 255 ;
}
if ( ! _paused )
update_volumes ( ) ;
2002-03-05 23:37:31 +00:00
return 0 ;
}
2003-08-01 20:39:16 +00:00
int IMuseInternal : : set_master_volume ( uint vol ) {
2002-11-17 17:59:00 +00:00
if ( vol > 255 )
vol = 255 ;
if ( _master_volume = = vol )
return 0 ;
2002-04-11 17:19:16 +00:00
_master_volume = vol ;
2002-11-17 17:59:00 +00:00
vol = vol * _music_volume / 255 ;
2003-08-01 20:39:16 +00:00
for ( uint i = 0 ; i < ARRAYSIZE ( _channel_volume ) ; i + + ) {
2002-11-17 17:59:00 +00:00
_channel_volume_eff [ i ] = _channel_volume [ i ] * vol / 255 ;
}
2002-11-16 14:23:22 +00:00
if ( ! _paused )
update_volumes ( ) ;
2001-12-01 17:23:50 +00:00
return 0 ;
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : get_master_volume ( ) {
2002-11-17 17:59:00 +00:00
return _master_volume ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : terminate ( ) {
2003-06-18 22:46:17 +00:00
stop_all_sounds ( ) ;
2003-05-26 14:51:13 +00:00
2003-05-16 01:52:45 +00:00
if ( _midi_adlib ) {
_midi_adlib - > close ( ) ;
delete _midi_adlib ;
_midi_adlib = 0 ;
}
if ( _midi_native ) {
_midi_native - > close ( ) ;
delete _midi_native ;
_midi_native = 0 ;
2002-08-22 12:09:06 +00:00
}
2003-05-16 01:52:45 +00:00
2001-12-01 17:23:50 +00:00
return 0 ;
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : enqueue_trigger ( int sound , int marker ) {
2001-12-01 17:23:50 +00:00
uint16 * p ;
uint pos ;
pos = _queue_pos ;
p = _cmd_queue [ pos ] . array ;
p [ 0 ] = TRIGGER_ID ;
p [ 1 ] = sound ;
p [ 2 ] = marker ;
2003-08-01 20:39:16 +00:00
pos = ( pos + 1 ) & ( ARRAYSIZE ( _cmd_queue ) - 1 ) ;
2002-04-11 17:19:16 +00:00
if ( _queue_end = = pos ) {
2003-08-01 20:39:16 +00:00
_queue_pos = ( pos - 1 ) & ( ARRAYSIZE ( _cmd_queue ) - 1 ) ;
2001-12-01 17:23:50 +00:00
return - 1 ;
}
2002-04-11 17:19:16 +00:00
2001-12-01 17:23:50 +00:00
_queue_pos = pos ;
_queue_adding = true ;
_queue_sound = sound ;
_queue_marker = marker ;
return 0 ;
}
2003-03-18 16:13:52 +00:00
int32 IMuseInternal : : doCommand ( int a , int b , int c , int d , int e , int f , int g , int h ) {
2003-08-06 18:20:15 +00:00
int args [ 8 ] ;
args [ 0 ] = a ;
args [ 1 ] = b ;
args [ 2 ] = c ;
args [ 3 ] = d ;
args [ 4 ] = e ;
args [ 5 ] = f ;
args [ 6 ] = g ;
args [ 7 ] = h ;
return doCommand ( 8 , args ) ;
}
int32 IMuseInternal : : doCommand ( int numargs , int a [ ] ) {
2002-10-12 04:57:49 +00:00
int i ;
2003-08-06 18:20:15 +00:00
if ( numargs < 1 ) return - 1 ;
byte cmd = a [ 0 ] & 0xFF ;
byte param = a [ 0 ] > > 8 ;
2002-04-11 17:19:16 +00:00
Player * player = NULL ;
2001-12-01 17:23:50 +00:00
2003-08-01 20:39:16 +00:00
if ( ! _initialized & & ( cmd | | param ) )
2001-12-01 17:23:50 +00:00
return - 1 ;
2003-05-07 19:24:14 +00:00
# ifdef IMUSE_DEBUG
2003-08-06 18:20:15 +00:00
{
char string [ 128 ] ;
sprintf ( string , " doCommand - %d (%d/%d) " , a [ 0 ] , ( int ) param , ( int ) cmd ) ;
for ( i = 1 ; i < numargs ; + + i )
sprintf ( string + strlen ( string ) , " , %d " , a [ i ] ) ;
debug ( 0 , string ) ;
}
2003-05-07 19:24:14 +00:00
# endif
2002-04-11 17:19:16 +00:00
if ( param = = 0 ) {
switch ( cmd ) {
2001-12-01 17:23:50 +00:00
case 6 :
2003-08-06 18:20:15 +00:00
if ( a [ 1 ] > 127 )
2002-11-17 17:59:00 +00:00
return - 1 ;
else
2003-08-06 18:20:15 +00:00
return set_master_volume ( ( a [ 1 ] < < 1 ) | ( a [ 1 ] ? 0 : 1 ) ) ; // Convert from 0-127 to 0-255
2001-12-01 17:23:50 +00:00
case 7 :
2002-11-17 17:59:00 +00:00
return _master_volume > > 1 ; // Convert from 0-255 to 0-127
2001-12-01 17:23:50 +00:00
case 8 :
2003-08-06 18:20:15 +00:00
return startSound ( a [ 1 ] ) ? 0 : - 1 ;
2001-12-01 17:23:50 +00:00
case 9 :
2003-08-06 18:20:15 +00:00
return stopSound ( a [ 1 ] ) ;
2002-10-10 15:16:58 +00:00
case 10 : // FIXME: Sam and Max - Not sure if this is correct
return stop_all_sounds ( ) ;
2001-12-01 17:23:50 +00:00
case 11 :
return stop_all_sounds ( ) ;
2002-10-14 16:42:57 +00:00
case 12 :
// Sam & Max: Player-scope commands
2003-08-06 18:20:15 +00:00
player = findActivePlayer ( a [ 1 ] ) ;
2003-05-23 04:19:47 +00:00
if ( ! player )
2002-10-14 16:42:57 +00:00
return - 1 ;
2003-08-06 18:20:15 +00:00
switch ( a [ 3 ] ) {
2002-10-14 16:42:57 +00:00
case 6 :
// Set player volume.
2003-08-06 18:20:15 +00:00
return player - > setVolume ( a [ 4 ] ) ;
2002-10-14 16:42:57 +00:00
default :
2003-08-06 18:20:15 +00:00
warning ( " IMuseInternal::doCommand(12) unsupported sub-command %d " , a [ 3 ] ) ;
2002-10-14 16:42:57 +00:00
}
return - 1 ;
2001-12-01 17:23:50 +00:00
case 13 :
2003-08-06 18:20:15 +00:00
return getSoundStatus ( a [ 1 ] ) ;
2002-10-12 04:57:49 +00:00
case 14 :
2003-05-23 04:19:47 +00:00
// Sam and Max: Parameter fade
2003-08-06 18:20:15 +00:00
player = this - > findActivePlayer ( a [ 1 ] ) ;
2003-05-20 01:12:40 +00:00
if ( player )
2003-08-06 18:20:15 +00:00
return player - > addParameterFader ( a [ 3 ] , a [ 4 ] , a [ 5 ] ) ;
2003-05-21 20:23:01 +00:00
return - 1 ;
2003-05-19 22:29:35 +00:00
2002-10-12 04:57:49 +00:00
case 15 :
2002-12-14 02:51:37 +00:00
// Sam & Max: Set hook for a "maybe" jump
2003-08-06 18:20:15 +00:00
player = findActivePlayer ( a [ 1 ] ) ;
2003-05-23 04:19:47 +00:00
if ( player ) {
2003-08-06 18:20:15 +00:00
player - > setHook ( 0 , a [ 3 ] , 0 ) ;
2003-05-23 04:19:47 +00:00
return 0 ;
2002-07-07 18:04:03 +00:00
}
2002-10-12 04:57:49 +00:00
return - 1 ;
case 16 :
2003-08-06 18:20:15 +00:00
return set_volchan ( a [ 1 ] , a [ 2 ] ) ;
2002-10-12 04:57:49 +00:00
case 17 :
2002-10-14 16:42:57 +00:00
if ( g_scumm - > _gameId ! = GID_SAMNMAX ) {
2003-08-06 18:20:15 +00:00
return set_channel_volume ( a [ 1 ] , a [ 2 ] ) ;
2002-10-14 16:42:57 +00:00
} else {
2003-08-06 18:20:15 +00:00
if ( a [ 4 ] ) {
int b [ 16 ] ;
memset ( b , 0 , sizeof ( b ) ) ;
for ( i = 0 ; i < numargs ; + + i )
b [ i ] = a [ i ] ;
return ImSetTrigger ( b [ 1 ] , b [ 3 ] , b [ 4 ] , b [ 5 ] , b [ 6 ] , b [ 7 ] , b [ 8 ] , b [ 9 ] , b [ 10 ] , b [ 11 ] ) ;
} else {
return ImClearTrigger ( a [ 1 ] , a [ 3 ] ) ;
}
2002-07-07 18:04:03 +00:00
}
2001-12-01 17:23:50 +00:00
case 18 :
2002-10-14 16:42:57 +00:00
if ( g_scumm - > _gameId ! = GID_SAMNMAX ) {
2003-08-06 18:20:15 +00:00
return set_volchan_entry ( a [ 1 ] , a [ 2 ] ) ;
2002-10-14 16:42:57 +00:00
} else {
// Sam & Max: ImCheckTrigger.
// According to Mike's notes to Ender,
// this function returns the number of triggers
// associated with a particular player ID and
// trigger ID.
2003-08-06 18:20:15 +00:00
a [ 0 ] = 0 ;
2002-10-14 16:42:57 +00:00
for ( i = 0 ; i < 16 ; + + i ) {
2003-08-06 18:20:15 +00:00
if ( _snm_triggers [ i ] . sound = = a [ 1 ] & & _snm_triggers [ i ] . id & &
( a [ 3 ] = = - 1 | | _snm_triggers [ i ] . id = = a [ 3 ] ) )
2002-10-14 16:42:57 +00:00
{
2003-08-06 18:20:15 +00:00
+ + a [ 0 ] ;
2002-10-14 16:42:57 +00:00
}
}
2003-08-06 18:20:15 +00:00
return a [ 0 ] ;
2002-10-14 16:42:57 +00:00
}
2002-04-21 17:54:59 +00:00
case 19 :
2002-10-14 16:42:57 +00:00
// Sam & Max: ImClearTrigger
// This should clear a trigger that's been set up
2003-08-01 20:39:16 +00:00
// with ImSetTrigger(cmd == 17). Seems to work....
2003-08-06 18:20:15 +00:00
return ImClearTrigger ( a [ 1 ] , a [ 3 ] ) ;
2002-12-13 15:49:30 +00:00
case 20 :
// Sam & Max: Deferred Command
2003-08-06 18:20:15 +00:00
addDeferredCommand ( a [ 1 ] , a [ 2 ] , a [ 3 ] , a [ 4 ] , a [ 5 ] , a [ 6 ] , a [ 7 ] ) ;
2003-05-20 01:12:40 +00:00
return 0 ;
2002-04-14 18:13:08 +00:00
case 2 :
case 3 :
return 0 ;
2001-12-01 17:23:50 +00:00
default :
2003-08-06 18:20:15 +00:00
warning ( " doCommand(%d [%d/%d], %d, %d, %d, %d, %d, %d, %d) unsupported " , a [ 0 ] , param , cmd , a [ 1 ] , a [ 2 ] , a [ 3 ] , a [ 4 ] , a [ 5 ] , a [ 6 ] , a [ 7 ] ) ;
2001-12-01 17:23:50 +00:00
}
2002-04-11 17:19:16 +00:00
} else if ( param = = 1 ) {
2003-08-01 20:39:16 +00:00
if ( ( 1 < < cmd ) & ( 0x783FFF ) ) {
2003-08-06 18:20:15 +00:00
player = findActivePlayer ( a [ 1 ] ) ;
2001-12-01 17:23:50 +00:00
if ( ! player )
return - 1 ;
2003-08-01 20:39:16 +00:00
if ( ( 1 < < cmd ) & ( 1 < < 11 | 1 < < 22 ) ) {
2003-08-06 18:20:15 +00:00
assert ( a [ 2 ] > = 0 & & a [ 2 ] < = 15 ) ;
player = ( Player * ) player - > getPart ( a [ 2 ] ) ;
2002-04-11 17:19:16 +00:00
if ( ! player )
2001-12-01 17:23:50 +00:00
return - 1 ;
}
}
2002-04-11 17:19:16 +00:00
switch ( cmd ) {
2001-12-01 17:23:50 +00:00
case 0 :
2002-11-10 18:34:57 +00:00
if ( g_scumm - > _gameId = = GID_SAMNMAX ) {
2003-08-06 18:20:15 +00:00
if ( a [ 3 ] = = 1 ) // Measure number
2003-05-23 04:19:47 +00:00
return ( ( player - > getBeatIndex ( ) - 1 ) > > 2 ) + 1 ;
2003-08-06 18:20:15 +00:00
else if ( a [ 3 ] = = 2 ) // Beat number
2003-05-23 04:19:47 +00:00
return player - > getBeatIndex ( ) ;
2002-11-10 18:34:57 +00:00
return - 1 ;
} else {
2003-08-06 18:20:15 +00:00
return player - > getParam ( a [ 2 ] , a [ 3 ] ) ;
2002-11-10 18:34:57 +00:00
}
2001-12-01 17:23:50 +00:00
case 1 :
2002-10-14 16:42:57 +00:00
if ( g_scumm - > _gameId = = GID_SAMNMAX )
2003-08-06 18:20:15 +00:00
player - > jump ( a [ 3 ] - 1 , ( a [ 4 ] - 1 ) * 4 + a [ 5 ] , ( ( a [ 6 ] * player - > getTicksPerBeat ( ) ) > > 2 ) + a [ 7 ] ) ;
2002-10-12 04:57:49 +00:00
else
2003-08-06 18:20:15 +00:00
player - > setPriority ( a [ 2 ] ) ;
2001-12-01 17:23:50 +00:00
return 0 ;
case 2 :
2003-08-06 18:20:15 +00:00
return player - > setVolume ( a [ 2 ] ) ;
2001-12-01 17:23:50 +00:00
case 3 :
2003-08-06 18:20:15 +00:00
player - > setPan ( a [ 2 ] ) ;
2001-12-01 17:23:50 +00:00
return 0 ;
case 4 :
2003-08-06 18:20:15 +00:00
return player - > setTranspose ( a [ 2 ] , a [ 3 ] ) ;
2001-12-01 17:23:50 +00:00
case 5 :
2003-08-06 18:20:15 +00:00
player - > setDetune ( a [ 2 ] ) ;
2001-12-01 17:23:50 +00:00
return 0 ;
case 6 :
2003-08-06 18:20:15 +00:00
player - > setSpeed ( a [ 2 ] ) ;
2001-12-01 17:23:50 +00:00
return 0 ;
case 7 :
2003-08-06 18:20:15 +00:00
return player - > jump ( a [ 2 ] , a [ 3 ] , a [ 4 ] ) ? 0 : - 1 ;
2001-12-01 17:23:50 +00:00
case 8 :
2003-08-06 18:20:15 +00:00
return player - > scan ( a [ 2 ] , a [ 3 ] , a [ 4 ] ) ;
2001-12-01 17:23:50 +00:00
case 9 :
2003-08-06 18:20:15 +00:00
return player - > setLoop ( a [ 2 ] , a [ 3 ] , a [ 4 ] , a [ 5 ] , a [ 6 ] ) ? 0 : - 1 ;
2001-12-01 17:23:50 +00:00
case 10 :
2003-05-23 04:19:47 +00:00
player - > clearLoop ( ) ;
2001-12-01 17:23:50 +00:00
return 0 ;
case 11 :
2003-08-06 18:20:15 +00:00
( ( Part * ) player ) - > set_onoff ( a [ 3 ] ! = 0 ) ;
2001-12-01 17:23:50 +00:00
return 0 ;
case 12 :
2003-08-06 18:20:15 +00:00
return player - > setHook ( a [ 2 ] , a [ 3 ] , a [ 4 ] ) ;
2001-12-01 17:23:50 +00:00
case 13 :
2003-08-06 18:20:15 +00:00
return player - > addParameterFader ( ParameterFader : : pfVolume , a [ 2 ] , a [ 3 ] ) ;
2001-12-01 17:23:50 +00:00
case 14 :
2003-08-06 18:20:15 +00:00
return enqueue_trigger ( a [ 1 ] , a [ 2 ] ) ;
2001-12-01 17:23:50 +00:00
case 15 :
2003-08-06 18:20:15 +00:00
return enqueue_command ( a [ 1 ] , a [ 2 ] , a [ 3 ] , a [ 4 ] , a [ 5 ] , a [ 6 ] , a [ 7 ] ) ;
2001-12-01 17:23:50 +00:00
case 16 :
return clear_queue ( ) ;
case 19 :
2003-08-06 18:20:15 +00:00
return player - > getParam ( a [ 2 ] , a [ 3 ] ) ;
2001-12-01 17:23:50 +00:00
case 20 :
2003-08-06 18:20:15 +00:00
return player - > setHook ( a [ 2 ] , a [ 3 ] , a [ 4 ] ) ;
2001-12-01 17:23:50 +00:00
case 21 :
return - 1 ;
case 22 :
2003-08-06 18:20:15 +00:00
( ( Part * ) player ) - > setVolume ( a [ 3 ] ) ;
2001-12-01 17:23:50 +00:00
return 0 ;
case 23 :
2003-08-06 18:20:15 +00:00
return query_queue ( a [ 1 ] ) ;
2001-12-01 17:23:50 +00:00
case 24 :
return 0 ;
default :
2003-08-06 18:20:15 +00:00
warning ( " doCommand(%d [%d/%d], %d, %d, %d, %d, %d, %d, %d) unsupported " , a [ 0 ] , param , cmd , a [ 1 ] , a [ 2 ] , a [ 3 ] , a [ 4 ] , a [ 5 ] , a [ 6 ] , a [ 7 ] ) ;
2001-12-01 17:23:50 +00:00
return - 1 ;
}
}
return - 1 ;
}
2003-08-06 18:20:15 +00:00
int32 IMuseInternal : : ImSetTrigger ( int sound , int id , int a , int b , int c , int d , int e , int f , int g , int h ) {
2002-11-23 16:15:33 +00:00
// Sam & Max: ImSetTrigger.
// Sets a trigger for a particular player and
2003-03-18 16:13:52 +00:00
// marker ID, along with doCommand parameters
2002-11-23 16:15:33 +00:00
// to invoke at the marker. The marker is
2003-08-01 20:39:16 +00:00
// represented by MIDI SysEx block 00 xx(F7)
2002-11-23 16:15:33 +00:00
// where "xx" is the marker ID.
uint16 oldest_trigger = 0 ;
2002-12-14 02:51:37 +00:00
ImTrigger * oldest_ptr = NULL ;
2002-11-23 16:15:33 +00:00
int i ;
2002-12-14 02:51:37 +00:00
ImTrigger * trig = _snm_triggers ;
2003-08-01 20:39:16 +00:00
for ( i = ARRAYSIZE ( _snm_triggers ) ; i ; - - i , + + trig ) {
2002-11-23 16:15:33 +00:00
if ( ! trig - > id )
break ;
if ( trig - > id = = id & & trig - > sound = = sound )
break ;
uint16 diff ;
if ( trig - > expire < = _snm_trigger_index )
diff = _snm_trigger_index - trig - > expire ;
else
diff = 0x10000 - trig - > expire + _snm_trigger_index ;
2002-12-14 02:51:37 +00:00
if ( ! oldest_ptr | | oldest_trigger < diff ) {
oldest_ptr = trig ;
2002-11-23 16:15:33 +00:00
oldest_trigger = diff ;
}
}
// If we didn't find a trigger, see if we can expire one.
2002-12-14 02:51:37 +00:00
if ( ! i ) {
if ( ! oldest_ptr )
2002-11-23 16:15:33 +00:00
return - 1 ;
2002-12-14 02:51:37 +00:00
trig = oldest_ptr ;
2002-11-23 16:15:33 +00:00
}
2002-12-14 02:51:37 +00:00
trig - > id = id ;
trig - > sound = sound ;
trig - > expire = ( + + _snm_trigger_index & 0xFFFF ) ;
trig - > command [ 0 ] = a ;
trig - > command [ 1 ] = b ;
trig - > command [ 2 ] = c ;
trig - > command [ 3 ] = d ;
2003-08-06 18:20:15 +00:00
trig - > command [ 4 ] = e ;
trig - > command [ 5 ] = f ;
trig - > command [ 6 ] = g ;
trig - > command [ 7 ] = h ;
2002-12-14 02:51:37 +00:00
// If the command is to start a sound, stop that sound if it's already playing.
// This fixes some carnival music problems.
2003-08-06 17:47:29 +00:00
// NOTE: We ONLY do this if the sound that will trigger the command is actually
// playing. Otherwise, there's a problem when exiting and re-entering the
// Bumpusville mansion. Ref Bug #780918.
if ( trig - > command [ 0 ] = = 8 & & getSoundStatus ( trig - > command [ 1 ] ) & & getSoundStatus ( sound ) )
2003-08-01 20:39:16 +00:00
stopSound ( trig - > command [ 1 ] ) ;
2002-11-23 16:15:33 +00:00
return 0 ;
}
2003-08-01 20:39:16 +00:00
int32 IMuseInternal : : ImClearTrigger ( int sound , int id ) {
2002-11-23 16:15:33 +00:00
int count = 0 ;
int i ;
2003-08-06 18:20:15 +00:00
ImTrigger * trig = _snm_triggers ;
for ( i = ARRAYSIZE ( _snm_triggers ) ; i ; - - i , + + trig ) {
if ( ( sound = = - 1 | | trig - > sound = = sound ) & &
trig - > id & & ( id = = - 1 | | trig - > id = = id ) )
2002-11-23 16:15:33 +00:00
{
2003-08-06 18:20:15 +00:00
trig - > sound = trig - > id = 0 ;
2002-11-23 16:15:33 +00:00
+ + count ;
}
}
return ( count > 0 ) ? 0 : - 1 ;
}
2003-08-01 20:39:16 +00:00
int32 IMuseInternal : : ImFireAllTriggers ( int sound ) {
2003-05-15 18:24:59 +00:00
if ( ! sound ) return 0 ;
int count = 0 ;
int i ;
for ( i = 0 ; i < 16 ; + + i ) {
if ( _snm_triggers [ i ] . sound = = sound )
{
_snm_triggers [ i ] . sound = _snm_triggers [ i ] . id = 0 ;
2003-08-06 18:20:15 +00:00
doCommand ( 8 , _snm_triggers [ i ] . command ) ;
2003-05-15 18:24:59 +00:00
+ + count ;
}
}
return ( count > 0 ) ? 0 : - 1 ;
}
2002-04-29 11:48:33 +00:00
int IMuseInternal : : set_channel_volume ( uint chan , uint vol )
2002-04-11 17:19:16 +00:00
{
if ( chan > = 8 | | vol > 127 )
2001-12-01 17:23:50 +00:00
return - 1 ;
_channel_volume [ chan ] = vol ;
2002-11-17 17:59:00 +00:00
_channel_volume_eff [ chan ] = _master_volume * _music_volume * vol / 255 / 255 ;
2001-12-01 17:23:50 +00:00
update_volumes ( ) ;
return 0 ;
}
2003-03-06 17:58:13 +00:00
void IMuseInternal : : update_volumes ( ) {
2001-12-01 17:23:50 +00:00
Player * player ;
int i ;
2002-04-11 17:19:16 +00:00
for ( i = ARRAYSIZE ( _players ) , player = _players ; i ! = 0 ; i - - , player + + ) {
2003-05-23 04:19:47 +00:00
if ( player - > isActive ( ) )
2003-08-01 20:39:16 +00:00
player - > setVolume ( player - > getVolume ( ) ) ;
2001-12-01 17:23:50 +00:00
}
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : set_volchan_entry ( uint a , uint b ) {
2001-12-01 17:23:50 +00:00
if ( a > = 8 )
return - 1 ;
_volchan_table [ a ] = b ;
return 0 ;
}
2003-03-06 17:58:13 +00:00
int HookDatas : : query_param ( int param , byte chan ) {
2002-04-11 17:19:16 +00:00
switch ( param ) {
2001-12-01 17:23:50 +00:00
case 18 :
2003-05-05 16:07:10 +00:00
return _jump [ 0 ] ;
2001-12-01 17:23:50 +00:00
case 19 :
return _transpose ;
case 20 :
return _part_onoff [ chan ] ;
case 21 :
return _part_volume [ chan ] ;
case 22 :
return _part_program [ chan ] ;
case 23 :
return _part_transpose [ chan ] ;
default :
return - 1 ;
}
}
2003-03-06 17:58:13 +00:00
int HookDatas : : set ( byte cls , byte value , byte chan ) {
2002-04-11 17:19:16 +00:00
switch ( cls ) {
2001-12-01 17:23:50 +00:00
case 0 :
2003-05-19 22:29:35 +00:00
if ( value ! = _jump [ 0 ] ) {
_jump [ 1 ] = _jump [ 0 ] ;
_jump [ 0 ] = value ;
}
2001-12-01 17:23:50 +00:00
break ;
case 1 :
_transpose = value ;
break ;
case 2 :
2002-04-11 17:19:16 +00:00
if ( chan < 16 )
2001-12-01 17:23:50 +00:00
_part_onoff [ chan ] = value ;
2002-04-11 17:19:16 +00:00
else if ( chan = = 16 )
2001-12-01 17:23:50 +00:00
memset ( _part_onoff , value , 16 ) ;
break ;
case 3 :
2002-04-11 17:19:16 +00:00
if ( chan < 16 )
2001-12-01 17:23:50 +00:00
_part_volume [ chan ] = value ;
2002-04-11 17:19:16 +00:00
else if ( chan = = 16 )
2001-12-01 17:23:50 +00:00
memset ( _part_volume , value , 16 ) ;
break ;
case 4 :
2002-04-11 17:19:16 +00:00
if ( chan < 16 )
2001-12-01 17:23:50 +00:00
_part_program [ chan ] = value ;
2002-04-11 17:19:16 +00:00
else if ( chan = = 16 )
2001-12-01 17:23:50 +00:00
memset ( _part_program , value , 16 ) ;
break ;
case 5 :
2002-04-11 17:19:16 +00:00
if ( chan < 16 )
2001-12-01 17:23:50 +00:00
_part_transpose [ chan ] = value ;
2002-04-11 17:19:16 +00:00
else if ( chan = = 16 )
2001-12-01 17:23:50 +00:00
memset ( _part_transpose , value , 16 ) ;
break ;
default :
return - 1 ;
}
return 0 ;
}
2003-08-01 20:39:16 +00:00
Player * IMuseInternal : : findActivePlayer ( int id ) {
2001-12-01 17:23:50 +00:00
int i ;
2003-05-23 04:19:47 +00:00
Player * player ;
2001-12-01 17:23:50 +00:00
2002-04-11 17:19:16 +00:00
for ( i = ARRAYSIZE ( _players ) , player = _players ; i ! = 0 ; i - - , player + + ) {
2003-05-23 04:19:47 +00:00
if ( player - > isActive ( ) & & player - > getID ( ) = = ( uint16 ) id )
return player ;
2001-12-01 17:23:50 +00:00
}
2003-05-23 04:19:47 +00:00
return NULL ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : get_volchan_entry ( uint a ) {
2002-04-11 17:19:16 +00:00
if ( a < 8 )
2001-12-01 17:23:50 +00:00
return _volchan_table [ a ] ;
return - 1 ;
}
2003-03-06 17:58:13 +00:00
uint32 IMuseInternal : : property ( int prop , uint32 value ) {
2002-07-07 18:04:03 +00:00
switch ( prop ) {
2002-04-29 11:48:33 +00:00
case IMuse : : PROP_TEMPO_BASE :
2003-05-16 22:28:33 +00:00
// This is a specified as a percentage of normal
// music speed. The number must be an integer
2003-08-01 20:39:16 +00:00
// ranging from 50 to 200(for 50% to 200% normal speed).
2003-05-16 22:28:33 +00:00
if ( value > = 50 & & value < = 200 )
_tempoFactor = value ;
2002-04-14 18:13:08 +00:00
break ;
2003-05-17 03:06:16 +00:00
case IMuse : : PROP_NATIVE_MT32 :
2003-08-01 20:39:16 +00:00
Instrument : : nativeMT32 ( value > 0 ) ;
2003-05-17 03:06:16 +00:00
break ;
case IMuse : : PROP_MULTI_MIDI :
_enable_multi_midi = ( value > 0 ) ;
2003-05-17 19:03:25 +00:00
if ( ! _enable_multi_midi & & _midi_native & & _midi_adlib ) {
MidiDriver * driver = _midi_adlib ;
_midi_adlib = NULL ;
int i ;
for ( i = 0 ; i < ARRAYSIZE ( _players ) ; + + i ) {
2003-05-23 04:19:47 +00:00
if ( _players [ i ] . isActive ( ) & & _players [ i ] . getMidiDriver ( ) = = driver )
2003-05-17 19:03:25 +00:00
_players [ i ] . clear ( ) ;
}
driver - > close ( ) ;
2003-08-05 23:58:24 +00:00
// FIXME: shouldn't we delete 'driver' here, too ?
2003-05-17 19:03:25 +00:00
}
2003-05-17 03:06:16 +00:00
break ;
2003-05-17 17:20:27 +00:00
case IMuse : : PROP_OLD_ADLIB_INSTRUMENTS :
_old_adlib_instruments = ( value > 0 ) ;
2003-05-23 18:35:53 +00:00
break ;
case IMuse : : PROP_LIMIT_PLAYERS :
if ( value > 0 & & value < = ARRAYSIZE ( _players ) )
_player_limit = ( int ) value ;
break ;
case IMuse : : PROP_RECYCLE_PLAYERS :
if ( value > 0 & & value < = ARRAYSIZE ( _players ) )
_recycle_players = ( value ! = 0 ) ;
break ;
2002-04-14 18:13:08 +00:00
}
return 0 ;
}
2003-03-06 17:58:13 +00:00
void IMuseInternal : : setBase ( byte * * base ) {
2002-04-14 18:13:08 +00:00
_base_sounds = base ;
}
2003-08-05 23:58:24 +00:00
IMuseInternal * IMuseInternal : : create ( OSystem * syst , SoundMixer * mixer , MidiDriver * native_midi ) {
2002-04-29 11:48:33 +00:00
IMuseInternal * i = new IMuseInternal ;
2003-08-05 23:58:24 +00:00
i - > initialize ( syst , mixer , native_midi ) ;
2002-04-14 18:13:08 +00:00
return i ;
}
2003-08-05 23:58:24 +00:00
int IMuseInternal : : initialize ( OSystem * syst , SoundMixer * mixer , MidiDriver * native_midi ) {
2001-12-01 17:23:50 +00:00
int i ;
2003-08-05 23:58:24 +00:00
_mixer = mixer ;
2003-05-16 22:00:33 +00:00
_midi_native = native_midi ;
_midi_adlib = NULL ;
if ( native_midi )
2003-08-01 20:39:16 +00:00
initMidiDriver ( _midi_native ) ;
2002-04-11 17:19:16 +00:00
2003-05-16 22:28:33 +00:00
if ( ! _tempoFactor ) _tempoFactor = 100 ;
2002-11-17 17:59:00 +00:00
_master_volume = 255 ;
2002-04-11 17:19:16 +00:00
if ( _music_volume < 1 )
2002-07-28 15:03:45 +00:00
_music_volume = kDefaultMusicVolume ;
2002-03-05 23:37:31 +00:00
2002-04-11 17:19:16 +00:00
for ( i = 0 ; i ! = 8 ; i + + )
2001-12-01 17:23:50 +00:00
_channel_volume [ i ] = _channel_volume_eff [ i ] = _volchan_table [ i ] = 127 ;
init_players ( ) ;
init_queue ( ) ;
init_parts ( ) ;
_initialized = true ;
2002-04-11 17:19:16 +00:00
2001-12-01 17:23:50 +00:00
return 0 ;
}
2003-08-01 20:39:16 +00:00
void IMuseInternal : : initMidiDriver ( MidiDriver * midi ) {
2003-05-16 01:52:45 +00:00
// Open MIDI driver
2003-07-15 02:16:33 +00:00
midi - > property ( MidiDriver : : PROP_OLD_ADLIB , _old_adlib_instruments ? 1 : 0 ) ;
2003-05-17 17:20:27 +00:00
2003-05-16 01:52:45 +00:00
int result = midi - > open ( ) ;
if ( result )
2003-06-12 07:46:48 +00:00
error ( " IMuse initialization - %s " , MidiDriver : : getErrorName ( result ) ) ;
2003-05-16 01:52:45 +00:00
2003-06-01 04:05:13 +00:00
// In case we have an MT-32 attached.
2003-07-15 02:16:33 +00:00
initMT32 ( midi ) ;
2003-06-01 00:42:01 +00:00
2003-05-16 01:52:45 +00:00
// Connect to the driver's timer
2003-07-15 02:16:33 +00:00
midi - > setTimerCallback ( midi , & IMuseInternal : : midiTimerCallback ) ;
2003-05-16 01:52:45 +00:00
}
2003-08-01 20:39:16 +00:00
void IMuseInternal : : initMT32 ( MidiDriver * midi ) {
2003-06-01 04:05:13 +00:00
byte buffer [ 32 ] = " \x41 \x10 \x16 \x12 \x00 \x00 \x00 " ;
2003-07-15 02:16:33 +00:00
char info [ 256 ] = " ScummVM " ;
int len ;
2003-08-01 20:39:16 +00:00
// Compute version string(truncated to 20 chars max.)
2003-07-15 02:16:33 +00:00
strcat ( info , gScummVMVersion ) ;
len = strlen ( info ) ;
if ( len > 20 )
len = 20 ;
2003-06-01 04:05:13 +00:00
// Reset the MT-32
2003-07-15 02:16:33 +00:00
memcpy ( & buffer [ 4 ] , " \x7f \x00 \x00 \x01 \x00 " , 5 ) ;
midi - > sysEx ( buffer , 9 ) ;
2003-06-01 04:05:13 +00:00
// Display a welcome message on MT-32 displays.
2003-07-15 02:16:33 +00:00
memcpy ( & buffer [ 4 ] , " \x20 \x00 \x00 " , 3 ) ;
memcpy ( & buffer [ 7 ] , " " , 20 ) ;
2003-08-01 20:39:16 +00:00
memcpy ( buffer + 7 + ( 20 - len ) / 2 , info , len ) ;
2003-06-01 04:05:13 +00:00
byte checksum = 0 ;
for ( int i = 4 ; i < 27 ; + + i )
checksum - = buffer [ i ] ;
buffer [ 27 ] = checksum ;
2003-08-01 20:39:16 +00:00
midi - > sysEx ( buffer , 28 ) ;
2003-06-01 04:05:13 +00:00
}
2003-03-06 17:58:13 +00:00
void IMuseInternal : : init_queue ( ) {
2001-12-01 17:23:50 +00:00
_queue_adding = false ;
_queue_pos = 0 ;
_queue_end = 0 ;
_trigger_count = 0 ;
}
2003-03-06 17:58:13 +00:00
void IMuseInternal : : pause ( bool paused ) {
2002-11-17 17:59:00 +00:00
int vol = _music_volume ;
if ( paused )
_music_volume = 0 ;
update_volumes ( ) ;
_music_volume = vol ;
2001-12-01 17:23:50 +00:00
_paused = paused ;
}
2003-08-01 20:39:16 +00:00
void IMuseInternal : : handleDeferredCommands ( MidiDriver * midi ) {
2003-05-23 04:19:47 +00:00
uint32 advance = midi - > getBaseTempo ( ) ;
2003-05-20 01:12:40 +00:00
DeferredCommand * ptr = & _deferredCommands [ 0 ] ;
int i ;
for ( i = ARRAYSIZE ( _deferredCommands ) ; i ; - - i , + + ptr ) {
if ( ! ptr - > time_left )
continue ;
if ( ptr - > time_left < = advance ) {
2003-07-15 02:16:33 +00:00
doCommand ( ptr - > a , ptr - > b , ptr - > c , ptr - > d , ptr - > e , ptr - > f , 0 , 0 ) ;
2003-05-20 01:12:40 +00:00
ptr - > time_left = advance ;
}
ptr - > time_left - = advance ;
}
}
2003-05-23 04:19:47 +00:00
// "time" is interpreted as hundredths of a second.
// FIXME: Is that correct?
2003-05-20 01:12:40 +00:00
// We convert it to microseconds before prceeding
2003-08-01 20:39:16 +00:00
void IMuseInternal : : addDeferredCommand ( int time , int a , int b , int c , int d , int e , int f ) {
2003-05-20 01:12:40 +00:00
DeferredCommand * ptr = & _deferredCommands [ 0 ] ;
int i ;
for ( i = ARRAYSIZE ( _deferredCommands ) ; i ; - - i , + + ptr ) {
if ( ! ptr - > time_left )
break ;
}
2003-05-26 20:42:25 +00:00
if ( i ) {
2003-05-20 01:12:40 +00:00
ptr - > time_left = time * 10000 ;
ptr - > a = a ;
ptr - > b = b ;
ptr - > c = c ;
ptr - > d = d ;
ptr - > e = e ;
ptr - > f = f ;
}
}
2003-05-22 16:15:48 +00:00
////////////////////////////////////////////////////////////
//
// IMuseInternal load/save implementation
//
2002-12-15 01:55:27 +00:00
////////////////////////////////////////////////////////////
2001-12-01 17:23:50 +00:00
enum {
TYPE_PART = 1 ,
2002-12-25 00:38:53 +00:00
TYPE_PLAYER = 2
2001-12-01 17:23:50 +00:00
} ;
2003-03-06 17:58:13 +00:00
int IMuseInternal : : saveReference ( void * me_ref , byte type , void * ref ) {
2002-12-08 16:14:29 +00:00
IMuseInternal * me = ( IMuseInternal * ) me_ref ;
2002-04-11 17:19:16 +00:00
switch ( type ) {
case TYPE_PART :
return ( Part * ) ref - me - > _parts ;
case TYPE_PLAYER :
return ( Player * ) ref - me - > _players ;
2001-12-01 17:23:50 +00:00
default :
error ( " saveReference: invalid type " ) ;
}
}
2003-03-06 17:58:13 +00:00
void * IMuseInternal : : loadReference ( void * me_ref , byte type , int ref ) {
2002-12-08 16:14:29 +00:00
IMuseInternal * me = ( IMuseInternal * ) me_ref ;
2002-04-11 17:19:16 +00:00
switch ( type ) {
case TYPE_PART :
return & me - > _parts [ ref ] ;
case TYPE_PLAYER :
return & me - > _players [ ref ] ;
2001-12-01 17:23:50 +00:00
default :
error ( " loadReference: invalid type " ) ;
}
}
2003-03-06 17:58:13 +00:00
int IMuseInternal : : save_or_load ( Serializer * ser , Scumm * scumm ) {
2001-12-01 17:23:50 +00:00
const SaveLoadEntry mainEntries [ ] = {
2002-12-08 16:14:29 +00:00
MKLINE ( IMuseInternal , _queue_end , sleUint8 , VER_V8 ) ,
MKLINE ( IMuseInternal , _queue_pos , sleUint8 , VER_V8 ) ,
MKLINE ( IMuseInternal , _queue_sound , sleUint16 , VER_V8 ) ,
MKLINE ( IMuseInternal , _queue_adding , sleByte , VER_V8 ) ,
MKLINE ( IMuseInternal , _queue_marker , sleByte , VER_V8 ) ,
MKLINE ( IMuseInternal , _queue_cleared , sleByte , VER_V8 ) ,
MKLINE ( IMuseInternal , _master_volume , sleByte , VER_V8 ) ,
MKLINE ( IMuseInternal , _trigger_count , sleUint16 , VER_V8 ) ,
MKARRAY ( IMuseInternal , _channel_volume [ 0 ] , sleUint16 , 8 , VER_V8 ) ,
MKARRAY ( IMuseInternal , _volchan_table [ 0 ] , sleUint16 , 8 , VER_V8 ) ,
2003-05-07 19:24:14 +00:00
// TODO: Add _cmd_queue in here
2001-12-01 17:23:50 +00:00
MKEND ( )
} ;
2002-04-11 17:19:16 +00:00
2003-05-21 21:38:03 +00:00
// VolumeFader is obsolete.
2001-12-01 17:23:50 +00:00
const SaveLoadEntry volumeFaderEntries [ ] = {
2003-05-21 20:23:01 +00:00
MK_OBSOLETE_REF ( VolumeFader , player , TYPE_PLAYER , VER_V8 , VER_V16 ) ,
MK_OBSOLETE ( VolumeFader , active , sleUint8 , VER_V8 , VER_V16 ) ,
MK_OBSOLETE ( VolumeFader , curvol , sleUint8 , VER_V8 , VER_V16 ) ,
MK_OBSOLETE ( VolumeFader , speed_lo_max , sleUint16 , VER_V8 , VER_V16 ) ,
MK_OBSOLETE ( VolumeFader , num_steps , sleUint16 , VER_V8 , VER_V16 ) ,
MK_OBSOLETE ( VolumeFader , speed_hi , sleInt8 , VER_V8 , VER_V16 ) ,
MK_OBSOLETE ( VolumeFader , direction , sleInt8 , VER_V8 , VER_V16 ) ,
MK_OBSOLETE ( VolumeFader , speed_lo , sleInt8 , VER_V8 , VER_V16 ) ,
MK_OBSOLETE ( VolumeFader , speed_lo_counter , sleUint16 , VER_V8 , VER_V16 ) ,
2001-12-01 17:23:50 +00:00
MKEND ( )
} ;
const SaveLoadEntry partEntries [ ] = {
2002-12-08 16:14:29 +00:00
MKREF ( Part , _next , TYPE_PART , VER_V8 ) ,
MKREF ( Part , _prev , TYPE_PART , VER_V8 ) ,
MKREF ( Part , _player , TYPE_PLAYER , VER_V8 ) ,
MKLINE ( Part , _pitchbend , sleInt16 , VER_V8 ) ,
MKLINE ( Part , _pitchbend_factor , sleUint8 , VER_V8 ) ,
MKLINE ( Part , _transpose , sleInt8 , VER_V8 ) ,
MKLINE ( Part , _vol , sleUint8 , VER_V8 ) ,
MKLINE ( Part , _detune , sleInt8 , VER_V8 ) ,
MKLINE ( Part , _pan , sleInt8 , VER_V8 ) ,
MKLINE ( Part , _on , sleUint8 , VER_V8 ) ,
MKLINE ( Part , _modwheel , sleUint8 , VER_V8 ) ,
MKLINE ( Part , _pedal , sleUint8 , VER_V8 ) ,
2003-05-15 23:08:03 +00:00
MK_OBSOLETE ( Part , _program , sleUint8 , VER_V8 , VER_V16 ) ,
2002-12-08 16:14:29 +00:00
MKLINE ( Part , _pri , sleUint8 , VER_V8 ) ,
MKLINE ( Part , _chan , sleUint8 , VER_V8 ) ,
MKLINE ( Part , _effect_level , sleUint8 , VER_V8 ) ,
MKLINE ( Part , _chorus , sleUint8 , VER_V8 ) ,
MKLINE ( Part , _percussion , sleUint8 , VER_V8 ) ,
MKLINE ( Part , _bank , sleUint8 , VER_V8 ) ,
2001-12-01 17:23:50 +00:00
MKEND ( )
} ;
2002-12-15 01:55:27 +00:00
# ifdef _WIN32_WCE // Don't break savegames made with andys' build
2002-04-11 17:19:16 +00:00
if ( ! ser - > isSaving ( ) & & ser - > checkEOFLoadStream ( ) )
return 0 ;
2003-04-30 13:23:31 +00:00
# elif defined(__PALM_OS__) // previous PalmOS ver. without imuse implementation or not saved(Oopps...forgot it !), is this really working ? will we have sound with old saved game ?
if ( ! ser - > isSaving ( ) & & ser - > checkEOFLoadStream ( ) )
return 0 ; //palmfixme
2002-04-11 17:19:16 +00:00
# endif
2002-03-14 14:45:04 +00:00
2003-05-21 21:38:03 +00:00
int i ;
2001-12-01 17:23:50 +00:00
ser - > _ref_me = this ;
2002-12-08 16:14:29 +00:00
ser - > _save_ref = saveReference ;
ser - > _load_ref = loadReference ;
2001-12-01 17:23:50 +00:00
ser - > saveLoadEntries ( this , mainEntries ) ;
2003-05-23 04:19:47 +00:00
for ( i = 0 ; i < ARRAYSIZE ( _players ) ; + + i )
2003-08-01 20:39:16 +00:00
_players [ i ] . save_or_load ( ser ) ;
2002-07-07 18:04:03 +00:00
ser - > saveLoadArrayOf ( _parts , ARRAYSIZE ( _parts ) , sizeof ( _parts [ 0 ] ) , partEntries ) ;
2002-12-21 20:10:47 +00:00
2002-12-21 23:19:42 +00:00
{ // Load/save the instrument definitions, which were revamped with V11.
2002-12-21 20:10:47 +00:00
Part * part = & _parts [ 0 ] ;
2002-12-21 23:19:42 +00:00
if ( ser - > getVersion ( ) > = VER_V11 ) {
for ( i = ARRAYSIZE ( _parts ) ; i ; - - i , + + part ) {
2003-08-01 20:39:16 +00:00
part - > _instrument . saveOrLoad ( ser ) ;
2002-12-21 23:19:42 +00:00
}
} else {
for ( i = ARRAYSIZE ( _parts ) ; i ; - - i , + + part )
part - > _instrument . clear ( ) ;
2002-12-21 20:10:47 +00:00
}
}
2003-05-21 20:23:01 +00:00
// VolumeFader has been replaced with the more generic ParameterFader.
2003-05-21 21:38:03 +00:00
for ( i = 0 ; i < 8 ; + + i )
2003-08-01 20:39:16 +00:00
ser - > saveLoadEntries ( 0 , volumeFaderEntries ) ;
2001-12-01 17:23:50 +00:00
if ( ! ser - > isSaving ( ) ) {
2002-12-15 01:55:27 +00:00
// Load all sounds that we need
2002-04-14 18:13:08 +00:00
fix_players_after_load ( scumm ) ;
2001-12-01 17:23:50 +00:00
fix_parts_after_load ( ) ;
2003-08-01 20:39:16 +00:00
set_master_volume ( _master_volume ) ;
2003-05-16 22:00:33 +00:00
if ( _midi_native )
2003-08-01 20:39:16 +00:00
reallocateMidiChannels ( _midi_native ) ;
2003-05-16 22:00:33 +00:00
if ( _midi_adlib )
2003-08-01 20:39:16 +00:00
reallocateMidiChannels ( _midi_adlib ) ;
2001-12-01 17:23:50 +00:00
}
return 0 ;
}
# undef MKLINE
# undef MKEND
2003-03-06 17:58:13 +00:00
void IMuseInternal : : fix_parts_after_load ( ) {
2001-12-01 17:23:50 +00:00
Part * part ;
int i ;
2002-04-11 17:19:16 +00:00
for ( i = ARRAYSIZE ( _parts ) , part = _parts ; i ! = 0 ; i - - , part + + ) {
2001-12-01 17:23:50 +00:00
if ( part - > _player )
part - > fix_after_load ( ) ;
}
}
2002-12-15 01:55:27 +00:00
// Only call this routine from the main thread,
// since it uses getResourceAddress
2003-03-06 17:58:13 +00:00
void IMuseInternal : : fix_players_after_load ( Scumm * scumm ) {
2001-12-01 17:23:50 +00:00
Player * player = _players ;
int i ;
2002-04-11 17:19:16 +00:00
for ( i = ARRAYSIZE ( _players ) ; i ! = 0 ; i - - , player + + ) {
2003-05-23 04:19:47 +00:00
if ( player - > isActive ( ) ) {
scumm - > getResourceAddress ( rtSound , player - > getID ( ) ) ;
player - > fixAfterLoad ( ) ;
2001-12-01 17:23:50 +00:00
}
}
}
2003-03-06 17:58:13 +00:00
void Part : : set_detune ( int8 detune ) {
2003-05-23 04:19:47 +00:00
_detune_eff = clamp ( ( _detune = detune ) + _player - > getDetune ( ) , - 128 , 127 ) ;
2003-05-16 15:48:01 +00:00
if ( _mc ) {
2003-08-01 20:39:16 +00:00
_mc - > pitchBend ( clamp ( _pitchbend +
2003-05-15 19:39:10 +00:00
( _detune_eff * 64 / 12 ) +
( _transpose_eff * 8192 / 12 ) , - 8192 , 8191 ) ) ;
}
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_pitchbend ( int value ) {
2002-09-24 23:45:25 +00:00
_pitchbend = value ;
2003-05-16 15:48:01 +00:00
if ( _mc ) {
2003-08-01 20:39:16 +00:00
_mc - > pitchBend ( clamp ( _pitchbend +
2003-05-15 19:39:10 +00:00
( _detune_eff * 64 / 12 ) +
( _transpose_eff * 8192 / 12 ) , - 8192 , 8191 ) ) ;
}
2001-12-01 17:23:50 +00:00
}
2003-05-23 04:19:47 +00:00
void Part : : setVolume ( uint8 vol ) {
_vol_eff = ( ( _vol = vol ) + 1 ) * _player - > getEffectiveVolume ( ) > > 7 ;
2003-05-16 15:48:01 +00:00
if ( _mc )
2003-08-01 20:39:16 +00:00
_mc - > volume ( _vol_eff ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_pri ( int8 pri ) {
2003-05-23 04:19:47 +00:00
_pri_eff = clamp ( ( _pri = pri ) + _player - > getPriority ( ) , 0 , 255 ) ;
2003-05-16 15:48:01 +00:00
if ( _mc )
2003-08-01 20:39:16 +00:00
_mc - > priority ( _pri_eff ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_pan ( int8 pan ) {
2003-05-23 04:19:47 +00:00
_pan_eff = clamp ( ( _pan = pan ) + _player - > getPan ( ) , - 64 , 63 ) ;
2003-05-16 15:48:01 +00:00
if ( _mc )
2003-08-01 20:39:16 +00:00
_mc - > panPosition ( _pan_eff + 0x40 ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_transpose ( int8 transpose ) {
2003-05-23 04:19:47 +00:00
_transpose_eff = transpose_clamp ( ( _transpose = transpose ) + _player - > getTranspose ( ) , - 12 , 12 ) ;
2003-05-16 15:48:01 +00:00
if ( _mc ) {
2003-08-01 20:39:16 +00:00
_mc - > pitchBend ( clamp ( _pitchbend +
2003-05-15 19:39:10 +00:00
( _detune_eff * 64 / 12 ) +
( _transpose_eff * 8192 / 12 ) , - 8192 , 8191 ) ) ;
}
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_pedal ( bool value ) {
2001-12-01 17:23:50 +00:00
_pedal = value ;
2003-05-16 15:48:01 +00:00
if ( _mc )
2003-08-01 20:39:16 +00:00
_mc - > sustain ( _pedal ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_modwheel ( uint value ) {
2001-12-01 17:23:50 +00:00
_modwheel = value ;
2003-05-16 15:48:01 +00:00
if ( _mc )
2003-08-01 20:39:16 +00:00
_mc - > modulationWheel ( _modwheel ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_chorus ( uint chorus ) {
2001-12-01 17:23:50 +00:00
_chorus = chorus ;
2003-05-16 15:48:01 +00:00
if ( _mc )
2003-08-01 20:39:16 +00:00
_mc - > chorusLevel ( _effect_level ) ;
2001-12-01 17:23:50 +00:00
}
2002-04-11 17:19:16 +00:00
void Part : : set_effect_level ( uint level )
{
2001-12-01 17:23:50 +00:00
_effect_level = level ;
2003-05-16 15:48:01 +00:00
if ( _mc )
2003-08-01 20:39:16 +00:00
_mc - > effectLevel ( _effect_level ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : fix_after_load ( ) {
2001-12-01 17:23:50 +00:00
set_transpose ( _transpose ) ;
2003-05-23 04:19:47 +00:00
setVolume ( _vol ) ;
2001-12-01 17:23:50 +00:00
set_detune ( _detune ) ;
set_pri ( _pri ) ;
set_pan ( _pan ) ;
2003-05-15 19:39:10 +00:00
sendAll ( ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_pitchbend_factor ( uint8 value ) {
2001-12-01 17:23:50 +00:00
if ( value > 12 )
return ;
set_pitchbend ( 0 ) ;
_pitchbend_factor = value ;
2003-05-16 15:48:01 +00:00
if ( _mc )
2003-08-01 20:39:16 +00:00
_mc - > pitchBendFactor ( _pitchbend_factor ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_onoff ( bool on ) {
2001-12-01 17:23:50 +00:00
if ( _on ! = on ) {
_on = on ;
if ( ! on )
off ( ) ;
if ( ! _percussion )
2003-08-01 20:39:16 +00:00
_player - > _se - > reallocateMidiChannels ( _player - > getMidiDriver ( ) ) ;
2001-12-01 17:23:50 +00:00
}
}
2003-03-06 17:58:13 +00:00
void Part : : set_instrument ( byte * data ) {
2003-08-01 20:39:16 +00:00
_instrument . adlib ( data ) ;
2003-05-16 15:48:01 +00:00
if ( clearToTransmit ( ) )
2003-08-01 20:39:16 +00:00
_instrument . send ( _mc ) ;
2001-12-01 17:23:50 +00:00
}
2003-08-01 20:39:16 +00:00
void Part : : load_global_instrument ( byte slot ) {
_player - > _se - > copyGlobalAdlibInstrument ( slot , & _instrument ) ;
2003-05-16 15:48:01 +00:00
if ( clearToTransmit ( ) )
2003-08-01 20:39:16 +00:00
_instrument . send ( _mc ) ;
2002-12-20 13:09:01 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : key_on ( byte note , byte velocity ) {
2003-05-07 19:24:14 +00:00
MidiChannel * mc = _mc ;
2003-08-01 20:39:16 +00:00
_actives [ note > > 4 ] | = ( 1 < < ( note & 0xF ) ) ;
2003-05-07 19:24:14 +00:00
// DEBUG
if ( _unassigned_instrument & & ! _percussion ) {
_unassigned_instrument = false ;
2003-05-15 19:39:10 +00:00
if ( ! _instrument . isValid ( ) ) {
2003-08-01 20:39:16 +00:00
warning ( " [%02d] No instrument specified " , ( int ) _chan ) ;
2003-05-15 19:39:10 +00:00
return ;
}
2003-05-07 19:24:14 +00:00
}
if ( mc & & _instrument . isValid ( ) ) {
2003-08-01 20:39:16 +00:00
mc - > noteOn ( note , velocity ) ;
2003-05-07 19:24:14 +00:00
} else if ( _percussion ) {
2003-05-23 04:19:47 +00:00
mc = _player - > getMidiDriver ( ) - > getPercussionChannel ( ) ;
2003-05-07 19:24:14 +00:00
if ( ! mc )
return ;
2003-08-01 20:39:16 +00:00
mc - > volume ( _vol_eff ) ;
mc - > programChange ( _bank ) ;
mc - > noteOn ( note , velocity ) ;
2003-05-07 19:24:14 +00:00
}
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : key_off ( byte note ) {
2003-05-07 19:24:14 +00:00
MidiChannel * mc = _mc ;
2003-08-01 20:39:16 +00:00
_actives [ note > > 4 ] & = ~ ( 1 < < ( note & 0xF ) ) ;
2003-05-07 19:24:14 +00:00
if ( mc ) {
2003-08-01 20:39:16 +00:00
mc - > noteOff ( note ) ;
2003-05-07 19:24:14 +00:00
} else if ( _percussion ) {
2003-05-23 04:19:47 +00:00
mc = _player - > getMidiDriver ( ) - > getPercussionChannel ( ) ;
2003-05-07 19:24:14 +00:00
if ( mc )
2003-08-01 20:39:16 +00:00
mc - > noteOff ( note ) ;
2003-05-07 19:24:14 +00:00
}
2001-12-01 17:23:50 +00:00
}
2003-05-16 01:52:45 +00:00
void Part : : init ( ) {
2001-12-01 17:23:50 +00:00
_player = NULL ;
_next = NULL ;
_prev = NULL ;
_mc = NULL ;
2003-08-01 20:39:16 +00:00
memset ( _actives , 0 , sizeof ( _actives ) ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : setup ( Player * player ) {
2001-12-01 17:23:50 +00:00
_player = player ;
2002-04-11 17:19:16 +00:00
2003-05-23 04:19:47 +00:00
_percussion = ( player - > isGM ( ) & & _chan = = 9 ) ; // true;
2001-12-01 17:23:50 +00:00
_on = true ;
2003-05-23 04:19:47 +00:00
_pri_eff = player - > getPriority ( ) ;
2001-12-01 17:23:50 +00:00
_pri = 0 ;
_vol = 127 ;
2003-05-23 04:19:47 +00:00
_vol_eff = player - > getEffectiveVolume ( ) ;
2003-08-01 20:39:16 +00:00
_pan = clamp ( player - > getPan ( ) , - 64 , 63 ) ;
2003-05-23 04:19:47 +00:00
_transpose_eff = player - > getTranspose ( ) ;
2001-12-01 17:23:50 +00:00
_transpose = 0 ;
_detune = 0 ;
2003-05-23 04:19:47 +00:00
_detune_eff = player - > getDetune ( ) ;
2002-10-14 16:42:57 +00:00
_pitchbend_factor = 2 ;
2001-12-01 17:23:50 +00:00
_pitchbend = 0 ;
_effect_level = 64 ;
2002-12-18 17:14:05 +00:00
_instrument . clear ( ) ;
2003-05-07 19:24:14 +00:00
_unassigned_instrument = true ;
2001-12-01 17:23:50 +00:00
_chorus = 0 ;
_modwheel = 0 ;
_bank = 0 ;
_pedal = false ;
_mc = NULL ;
}
2003-03-06 17:58:13 +00:00
void Part : : uninit ( ) {
2001-12-01 17:23:50 +00:00
if ( ! _player )
return ;
off ( ) ;
2003-08-01 20:39:16 +00:00
_player - > removePart ( this ) ;
2001-12-01 17:23:50 +00:00
_player = NULL ;
}
2003-03-06 17:58:13 +00:00
void Part : : off ( ) {
2003-05-15 22:31:56 +00:00
if ( _mc ) {
_mc - > allNotesOff ( ) ;
_mc - > release ( ) ;
_mc = NULL ;
}
2003-08-01 20:39:16 +00:00
memset ( _actives , 0 , sizeof ( _actives ) ) ;
2001-12-01 17:23:50 +00:00
}
2003-05-15 19:39:10 +00:00
bool Part : : clearToTransmit ( ) {
if ( _mc ) return true ;
2003-08-01 20:39:16 +00:00
if ( _instrument . isValid ( ) ) _player - > _se - > reallocateMidiChannels ( _player - > getMidiDriver ( ) ) ;
2003-05-15 19:39:10 +00:00
return false ;
2001-12-01 17:23:50 +00:00
}
2003-05-15 19:39:10 +00:00
void Part : : sendAll ( ) {
if ( ! clearToTransmit ( ) ) return ;
2003-08-01 20:39:16 +00:00
_mc - > pitchBendFactor ( _pitchbend_factor ) ;
_mc - > pitchBend ( clamp ( _pitchbend +
( _detune_eff * 64 / 12 ) +
( _transpose_eff * 8192 / 12 ) , - 8192 , 8191 ) ) ;
_mc - > volume ( _vol_eff ) ;
_mc - > sustain ( _pedal ) ;
_mc - > modulationWheel ( _modwheel ) ;
_mc - > panPosition ( _pan_eff + 0x40 ) ;
_mc - > effectLevel ( _effect_level ) ;
2003-05-16 04:02:33 +00:00
if ( _instrument . isValid ( ) )
2003-08-01 20:39:16 +00:00
_instrument . send ( _mc ) ;
_mc - > chorusLevel ( _effect_level ) ;
_mc - > priority ( _pri_eff ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
int Part : : update_actives ( uint16 * active ) {
2003-05-15 19:39:10 +00:00
int i , j ;
uint16 * act , mask , bits ;
int count = 0 ;
bits = 1 < < _chan ;
act = _actives ;
for ( i = 8 ; i ; i - - ) {
mask = * act + + ;
if ( mask ) {
for ( j = 16 ; j ; j - - , mask > > = 1 , active + + ) {
if ( mask & 1 & & ! ( * active & bits ) ) {
* active | = bits ;
count + + ;
}
}
} else {
active + = 16 ;
}
}
return count ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_program ( byte program ) {
2003-05-15 23:08:03 +00:00
_bank = 0 ;
2003-08-01 20:39:16 +00:00
_instrument . program ( program , _player - > isMT32 ( ) ) ;
2003-05-16 15:48:01 +00:00
if ( clearToTransmit ( ) )
2003-08-01 20:39:16 +00:00
_instrument . send ( _mc ) ;
2001-12-01 17:23:50 +00:00
}
2003-03-06 17:58:13 +00:00
void Part : : set_instrument ( uint b ) {
2002-04-11 17:19:16 +00:00
_bank = ( byte ) ( b > > 8 ) ;
2003-08-01 20:39:16 +00:00
_instrument . program ( ( byte ) b , _player - > isMT32 ( ) ) ;
2003-05-16 15:48:01 +00:00
if ( clearToTransmit ( ) )
2003-08-01 20:39:16 +00:00
_instrument . send ( _mc ) ;
2002-04-14 18:13:08 +00:00
}
2003-05-23 04:19:47 +00:00
void Part : : silence ( ) {
if ( ! _mc )
return ;
_mc - > allNotesOff ( ) ;
2003-08-01 20:39:16 +00:00
memset ( _actives , 0 , sizeof ( _actives ) ) ;
2003-05-23 04:19:47 +00:00
}
2002-12-15 01:55:27 +00:00
////////////////////////////////////////
//
2003-05-16 01:52:45 +00:00
// Some more IMuseInternal stuff
2002-12-15 01:55:27 +00:00
//
////////////////////////////////////////
2002-04-14 18:13:08 +00:00
2003-08-01 20:39:16 +00:00
void IMuseInternal : : midiTimerCallback ( void * data ) {
2003-05-16 01:52:45 +00:00
MidiDriver * driver = ( MidiDriver * ) data ;
2002-12-03 17:54:25 +00:00
if ( g_scumm - > _imuse )
2003-08-01 20:39:16 +00:00
g_scumm - > _imuse - > on_timer ( driver ) ;
2002-08-22 12:09:06 +00:00
}
2003-08-01 20:39:16 +00:00
void IMuseInternal : : reallocateMidiChannels ( MidiDriver * midi ) {
2002-04-14 18:13:08 +00:00
Part * part , * hipart ;
int i ;
byte hipri , lopri ;
2002-11-26 16:54:58 +00:00
Part * lopart ;
2002-04-14 18:13:08 +00:00
while ( true ) {
hipri = 0 ;
hipart = NULL ;
2003-05-15 22:31:56 +00:00
for ( i = 32 , part = _parts ; i ; i - - , part + + ) {
2003-05-23 04:19:47 +00:00
if ( part - > _player & & part - > _player - > getMidiDriver ( ) = = midi & &
2003-05-16 01:52:45 +00:00
! part - > _percussion & & part - > _on & &
! part - > _mc & & part - > _pri_eff > = hipri )
{
2002-04-14 18:13:08 +00:00
hipri = part - > _pri_eff ;
hipart = part ;
}
}
if ( ! hipart )
return ;
2003-05-16 01:52:45 +00:00
if ( ( hipart - > _mc = midi - > allocateChannel ( ) ) = = NULL ) {
2002-12-18 17:14:05 +00:00
lopri = 255 ;
lopart = NULL ;
2003-05-15 22:31:56 +00:00
for ( i = 32 , part = _parts ; i ; i - - , part + + ) {
2003-05-16 01:52:45 +00:00
if ( part - > _mc & & part - > _mc - > device ( ) = = midi & & part - > _pri_eff < = lopri ) {
2002-12-18 17:14:05 +00:00
lopri = part - > _pri_eff ;
lopart = part ;
}
2002-04-14 18:13:08 +00:00
}
2002-12-18 17:14:05 +00:00
if ( lopart = = NULL | | lopri > = hipri )
return ;
lopart - > off ( ) ;
2002-11-26 16:54:58 +00:00
2003-05-16 01:52:45 +00:00
if ( ( hipart - > _mc = midi - > allocateChannel ( ) ) = = NULL )
2002-12-18 17:14:05 +00:00
return ;
}
2003-05-15 19:39:10 +00:00
hipart - > sendAll ( ) ;
2002-04-14 18:13:08 +00:00
}
}
2003-08-01 20:39:16 +00:00
void IMuseInternal : : setGlobalAdlibInstrument ( byte slot , byte * data ) {
2002-12-18 13:22:40 +00:00
if ( slot < 32 ) {
2003-08-01 20:39:16 +00:00
_global_adlib_instruments [ slot ] . adlib ( data ) ;
2002-12-18 13:22:40 +00:00
}
2002-11-21 19:06:42 +00:00
}
2003-08-01 20:39:16 +00:00
void IMuseInternal : : copyGlobalAdlibInstrument ( byte slot , Instrument * dest ) {
2002-12-20 13:09:01 +00:00
if ( slot > = 32 )
return ;
2003-08-01 20:39:16 +00:00
_global_adlib_instruments [ slot ] . copy_to ( dest ) ;
2002-12-20 13:09:01 +00:00
}
2002-12-21 21:09:36 +00:00
////////////////////////////////////////////////////////////
//
// IMuse implementation
//
// IMuse actually serves as a concurency monitor front-end
// to IMuseInternal and ensures that only one thread
// accesses the object at a time. This is necessary to
// prevent scripts and the MIDI parser from yanking objects
// out from underneath each other.
//
////////////////////////////////////////////////////////////
2003-08-01 20:39:16 +00:00
IMuse : : IMuse ( OSystem * system , IMuseInternal * target ) : _system ( system ) , _target ( target ) { _mutex = system - > create_mutex ( ) ; }
IMuse : : ~ IMuse ( ) { if ( _mutex ) _system - > delete_mutex ( _mutex ) ; if ( _target ) delete _target ; }
inline void IMuse : : in ( ) { _system - > lock_mutex ( _mutex ) ; }
inline void IMuse : : out ( ) { _system - > unlock_mutex ( _mutex ) ; }
2002-12-21 21:09:36 +00:00
2003-08-01 20:39:16 +00:00
void IMuse : : on_timer ( MidiDriver * midi ) { in ( ) ; _target - > on_timer ( midi ) ; out ( ) ; }
void IMuse : : pause ( bool paused ) { in ( ) ; _target - > pause ( paused ) ; out ( ) ; }
int IMuse : : save_or_load ( Serializer * ser , Scumm * scumm ) { in ( ) ; int ret = _target - > save_or_load ( ser , scumm ) ; out ( ) ; return ret ; }
int IMuse : : set_music_volume ( uint vol ) { in ( ) ; int ret = _target - > set_music_volume ( vol ) ; out ( ) ; return ret ; }
2002-12-21 21:09:36 +00:00
int IMuse : : get_music_volume ( ) { in ( ) ; int ret = _target - > get_music_volume ( ) ; out ( ) ; return ret ; }
2003-08-01 20:39:16 +00:00
int IMuse : : set_master_volume ( uint vol ) { in ( ) ; int ret = _target - > set_master_volume ( vol ) ; out ( ) ; return ret ; }
2002-12-21 21:09:36 +00:00
int IMuse : : get_master_volume ( ) { in ( ) ; int ret = _target - > get_master_volume ( ) ; out ( ) ; return ret ; }
2003-08-01 20:39:16 +00:00
bool IMuse : : startSound ( int sound ) { in ( ) ; bool ret = _target - > startSound ( sound ) ; out ( ) ; return ret ; }
int IMuse : : stopSound ( int sound ) { in ( ) ; int ret = _target - > stopSound ( sound ) ; out ( ) ; return ret ; }
2002-12-21 21:09:36 +00:00
int IMuse : : stop_all_sounds ( ) { in ( ) ; int ret = _target - > stop_all_sounds ( ) ; out ( ) ; return ret ; }
2003-08-01 20:39:16 +00:00
int IMuse : : getSoundStatus ( int sound ) { in ( ) ; int ret = _target - > getSoundStatus ( sound , true ) ; out ( ) ; return ret ; }
bool IMuse : : get_sound_active ( int sound ) { in ( ) ; bool ret = _target - > getSoundStatus ( sound , false ) ? 1 : 0 ; out ( ) ; return ret ; }
2003-08-06 18:20:15 +00:00
int32 IMuse : : doCommand ( int a , int b , int c , int d , int e , int f , int g , int h ) { in ( ) ; int32 ret = _target - > doCommand ( a , b , c , d , e , f , g , h ) ; out ( ) ; return ret ; }
int32 IMuse : : doCommand ( int numargs , int args [ ] ) { in ( ) ; int32 ret = _target - > doCommand ( numargs , args ) ; out ( ) ; return ret ; }
2002-12-21 21:09:36 +00:00
int IMuse : : clear_queue ( ) { in ( ) ; int ret = _target - > clear_queue ( ) ; out ( ) ; return ret ; }
2003-08-01 20:39:16 +00:00
void IMuse : : setBase ( byte * * base ) { in ( ) ; _target - > setBase ( base ) ; out ( ) ; }
uint32 IMuse : : property ( int prop , uint32 value ) { in ( ) ; uint32 ret = _target - > property ( prop , value ) ; out ( ) ; return ret ; }
2003-05-19 05:04:38 +00:00
MidiDriver * IMuse : : getMidiDriver ( ) { in ( ) ; MidiDriver * ret = _target - > getMidiDriver ( ) ; out ( ) ; return ret ; }
2002-12-21 21:09:36 +00:00
2002-10-21 07:31:51 +00:00
// The IMuse::create method provides a front-end factory
// for creating IMuseInternal without exposing that class
// to the client.
2003-08-05 23:58:24 +00:00
IMuse * IMuse : : create ( OSystem * syst , SoundMixer * mixer , MidiDriver * midi ) {
IMuseInternal * engine = IMuseInternal : : create ( syst , mixer , midi ) ;
2003-08-01 20:39:16 +00:00
return new IMuse ( syst , engine ) ;
2002-04-29 11:48:33 +00:00
}