2012-04-25 12:49:49 +10:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
2014-02-18 02:34:26 +01:00
*
2012-04-25 12:49:49 +10: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 .
2014-02-18 02:34:26 +01:00
*
2012-04-25 12:49:49 +10: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 . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
*/
2012-04-26 09:43:55 +10:00
# include "common/scummsys.h"
# include "common/algorithm.h"
2012-04-29 11:23:02 +10:00
# include "common/config-manager.h"
2012-05-06 21:24:55 +10:00
# include "common/debug-channels.h"
2012-05-05 20:54:21 +10:00
# include "common/events.h"
2012-04-26 09:43:55 +10:00
# include "common/file.h"
2012-05-28 16:56:31 -04:00
# include "common/installshield_cab.h"
2016-12-05 15:29:23 +01:00
# include "common/translation.h"
2012-04-25 12:49:49 +10:00
# include "tony/tony.h"
2012-05-06 12:21:29 +10:00
# include "tony/custom.h"
2012-05-22 00:29:27 +10:00
# include "tony/debugger.h"
2012-05-01 23:00:03 +10:00
# include "tony/game.h"
2012-04-26 09:43:55 +10:00
# include "tony/mpal/mpal.h"
2012-04-25 12:49:49 +10:00
namespace Tony {
2012-08-22 14:00:46 +02:00
TonyEngine * g_vm ;
2012-04-25 12:49:49 +10:00
2012-05-21 23:53:13 +02:00
TonyEngine : : TonyEngine ( OSystem * syst , const TonyGameDescription * gameDesc ) : Engine ( syst ) ,
_gameDescription ( gameDesc ) , _randomSource ( " tony " ) {
2012-08-22 14:00:46 +02:00
g_vm = this ;
2012-05-18 22:57:25 +10:00
_loadSlotNumber = - 1 ;
2012-05-06 21:24:55 +10:00
2012-06-17 17:04:10 +10:00
// Set the up the debugger
2012-05-22 00:29:27 +10:00
_debugger = new Debugger ( ) ;
2012-05-06 21:24:55 +10:00
DebugMan . addDebugChannel ( kTonyDebugAnimations , " animations " , " Animations debugging " ) ;
DebugMan . addDebugChannel ( kTonyDebugActions , " actions " , " Actions debugging " ) ;
DebugMan . addDebugChannel ( kTonyDebugSound , " sound " , " Sound debugging " ) ;
DebugMan . addDebugChannel ( kTonyDebugMusic , " music " , " Music debugging " ) ;
2012-05-16 00:05:48 +10:00
2012-06-06 23:18:56 +10:00
// Add folders to the search directory list
const Common : : FSNode gameDataDir ( ConfMan . get ( " path " ) ) ;
SearchMan . addSubDirectoryMatching ( gameDataDir , " Voices " ) ;
SearchMan . addSubDirectoryMatching ( gameDataDir , " Roasted " ) ;
SearchMan . addSubDirectoryMatching ( gameDataDir , " Music " ) ;
2012-08-25 12:56:02 +02:00
SearchMan . addSubDirectoryMatching ( gameDataDir , " Music/utilsfx " ) ;
2012-10-15 07:08:24 +02:00
SearchMan . addSubDirectoryMatching ( gameDataDir , " Music/Layer " ) ;
2012-06-06 23:18:56 +10:00
2012-05-16 00:05:48 +10:00
// Set up load slot number
2012-05-18 22:57:25 +10:00
_initialLoadSlotNumber = - 1 ;
2012-05-16 00:05:48 +10:00
if ( ConfMan . hasKey ( " save_slot " ) ) {
int slotNumber = ConfMan . getInt ( " save_slot " ) ;
if ( slotNumber > = 0 & & slotNumber < = 99 )
2012-05-18 22:57:25 +10:00
_initialLoadSlotNumber = slotNumber ;
2012-05-16 00:05:48 +10:00
}
2012-06-15 08:42:24 +02:00
2012-06-17 17:04:10 +10:00
// Load the ScummVM sound settings
syncSoundSettings ( ) ;
2012-06-15 08:42:24 +02:00
_hEndOfFrame = 0 ;
for ( int i = 0 ; i < 6 ; i + + )
_stream [ i ] = NULL ;
for ( int i = 0 ; i < MAX_SFX_CHANNELS ; i + + ) {
_sfx [ i ] = NULL ;
_utilSfx [ i ] = NULL ;
}
_bPaused = false ;
_bDrawLocation = false ;
_startTime = 0 ;
_curThumbnail = NULL ;
_bQuitNow = false ;
_bTimeFreezed = false ;
_nTimeFreezed = 0 ;
2016-01-04 14:10:24 +01:00
_vdbCodec = FPCODEC_UNKNOWN ;
2016-06-17 12:06:46 +02:00
memset ( _funcList , 0 , sizeof ( _funcList ) ) ;
2012-04-25 12:49:49 +10:00
}
TonyEngine : : ~ TonyEngine ( ) {
2012-04-29 11:23:02 +10:00
// Close the voice database
2012-06-04 23:45:36 +02:00
closeVoiceDatabase ( ) ;
2012-05-11 23:15:59 +10:00
// Reset the coroutine scheduler
CoroScheduler . reset ( ) ;
2012-08-28 09:19:10 +02:00
CoroScheduler . setResourceCallback ( NULL ) ;
2012-05-22 00:29:27 +10:00
delete _debugger ;
2012-04-25 12:49:49 +10:00
}
2012-04-26 09:43:55 +10:00
/**
* Run the game
*/
2012-04-25 12:49:49 +10:00
Common : : Error TonyEngine : : run ( ) {
2012-06-04 23:45:36 +02:00
Common : : ErrorCode result = init ( ) ;
2012-04-26 09:43:55 +10:00
if ( result ! = Common : : kNoError )
return result ;
2012-06-04 23:45:36 +02:00
play ( ) ;
close ( ) ;
2012-04-30 23:16:19 +10:00
2012-04-26 09:43:55 +10:00
return Common : : kNoError ;
}
/**
2012-06-17 18:36:23 +02:00
* Initialize the game
2012-04-26 09:43:55 +10:00
*/
2012-06-04 23:45:36 +02:00
Common : : ErrorCode TonyEngine : : init ( ) {
2012-08-26 23:33:46 +02:00
// Load DAT file (used by font manager)
if ( ! loadTonyDat ( ) )
return Common : : kUnknownError ;
2012-05-28 16:56:31 -04:00
if ( isCompressed ( ) ) {
Common : : SeekableReadStream * stream = SearchMan . createReadStreamForMember ( " data1.cab " ) ;
if ( ! stream )
error ( " Failed to open data1.cab " ) ;
Common : : Archive * cabinet = Common : : makeInstallShieldArchive ( stream ) ;
if ( ! cabinet )
error ( " Failed to parse data1.cab " ) ;
SearchMan . add ( " data1.cab " , cabinet ) ;
}
2012-06-04 23:45:36 +02:00
_hEndOfFrame = CoroScheduler . createEvent ( false , false ) ;
2012-04-30 23:16:19 +10:00
2012-06-04 23:45:36 +02:00
_bPaused = false ;
_bDrawLocation = true ;
_startTime = g_system - > getMillis ( ) ;
2012-04-30 23:16:19 +10:00
2012-05-21 23:53:13 +02:00
// Init static class fields
2012-06-05 08:39:55 +02:00
RMText : : initStatics ( ) ;
RMTony : : initStatics ( ) ;
2012-05-13 23:05:41 +10:00
2012-05-06 12:21:29 +10:00
// Reset the scheduler
2012-05-11 23:15:59 +10:00
CoroScheduler . reset ( ) ;
2012-05-06 12:21:29 +10:00
2012-06-17 18:36:23 +02:00
// Initialize the graphics window
2012-06-05 08:39:55 +02:00
_window . init ( ) ;
2012-05-05 20:54:21 +10:00
2012-06-17 18:36:23 +02:00
// Initialize the function list
2012-06-04 23:45:36 +02:00
Common : : fill ( _funcList , _funcList + 300 , ( LPCUSTOMFUNCTION ) NULL ) ;
initCustomFunctionMap ( ) ;
2012-04-26 09:43:55 +10:00
// Initializes MPAL system, passing the custom functions list
Common : : File f ;
if ( ! f . open ( " ROASTED.MPC " ) )
return Common : : kReadingFailed ;
f . close ( ) ;
2012-06-04 23:45:36 +02:00
if ( ! mpalInit ( " ROASTED.MPC " , " ROASTED.MPR " , _funcList , _funcListStrings ) )
2012-04-26 09:43:55 +10:00
return Common : : kUnknownError ;
2012-06-17 18:36:23 +02:00
// Initialize the update resources
2012-06-07 08:42:35 +02:00
_resUpdate . init ( " ROASTED.MPU " ) ;
2012-04-29 10:49:14 +10:00
2012-06-17 18:36:23 +02:00
// Initialize the music
2012-06-04 23:45:36 +02:00
initMusic ( ) ;
2012-04-29 11:23:02 +10:00
2012-06-17 18:36:23 +02:00
// Initialize the voices database
2012-06-04 23:45:36 +02:00
if ( ! openVoiceDatabase ( ) )
2012-04-29 11:23:02 +10:00
return Common : : kReadingFailed ;
2012-06-17 18:36:23 +02:00
// Initialize the boxes
2012-06-07 07:58:01 +02:00
_theBoxes . init ( ) ;
2012-04-29 23:19:30 +10:00
2012-04-30 09:27:12 +10:00
// Link to the custom graphics engine
2012-06-05 01:04:53 +02:00
_theEngine . initCustomDll ( ) ;
_theEngine . init ( ) ;
2012-05-01 23:00:03 +10:00
2012-05-20 13:54:59 +10:00
// Allocate space for thumbnails when saving the game
2012-06-04 23:45:36 +02:00
_curThumbnail = new uint16 [ 160 * 120 ] ;
2012-05-01 23:00:03 +10:00
2012-06-04 23:45:36 +02:00
_bQuitNow = false ;
2012-04-30 09:27:12 +10:00
2012-04-25 12:49:49 +10:00
return Common : : kNoError ;
}
2012-08-26 23:33:46 +02:00
bool TonyEngine : : loadTonyDat ( ) {
Common : : String msg ;
Common : : File in ;
2016-12-05 15:29:23 +01:00
Common : : String filename = " tony.dat " ;
2012-08-26 23:33:46 +02:00
2016-12-05 15:29:23 +01:00
in . open ( filename . c_str ( ) ) ;
2012-08-26 23:33:46 +02:00
if ( ! in . isOpen ( ) ) {
2016-12-05 15:29:23 +01:00
msg = Common : : String : : format ( _ ( " You're missing the '%s' file. Get it from the ScummVM website " ) , filename . c_str ( ) ) ;
2012-08-26 23:33:46 +02:00
GUIErrorMessage ( msg ) ;
warning ( " %s " , msg . c_str ( ) ) ;
return false ;
}
// Read header
char buf [ 4 + 1 ] ;
in . read ( buf , 4 ) ;
buf [ 4 ] = ' \0 ' ;
if ( strcmp ( buf , " TONY " ) ) {
2016-12-05 21:07:11 +01:00
msg = Common : : String : : format ( _ ( " File '%s' is corrupt. Get it from the ScummVM website " ) , filename . c_str ( ) ) ;
2012-08-26 23:33:46 +02:00
GUIErrorMessage ( msg ) ;
warning ( " %s " , msg . c_str ( ) ) ;
return false ;
}
int majVer = in . readByte ( ) ;
int minVer = in . readByte ( ) ;
if ( ( majVer ! = TONY_DAT_VER_MAJ ) | | ( minVer ! = TONY_DAT_VER_MIN ) ) {
msg = Common : : String : : format ( " File 'tony.dat' is wrong version. Expected %d.%d but got %d.%d. Get it from the ScummVM website " , TONY_DAT_VER_MAJ , TONY_DAT_VER_MIN , majVer , minVer ) ;
GUIErrorMessage ( msg ) ;
warning ( " %s " , msg . c_str ( ) ) ;
return false ;
}
int expectedLangVariant = - 1 ;
switch ( g_vm - > getLanguage ( ) ) {
case Common : : IT_ITA :
2012-08-26 23:58:06 +02:00
case Common : : EN_ANY :
2012-08-26 23:33:46 +02:00
expectedLangVariant = 0 ;
break ;
case Common : : PL_POL :
expectedLangVariant = 1 ;
break ;
case Common : : RU_RUS :
expectedLangVariant = 2 ;
break ;
case Common : : CZ_CZE :
expectedLangVariant = 3 ;
break ;
case Common : : FR_FRA :
expectedLangVariant = 4 ;
break ;
case Common : : DE_DEU :
expectedLangVariant = 5 ;
break ;
default :
2012-08-27 00:17:28 +02:00
warning ( " Unhandled language, falling back to English/Italian fonts. " ) ;
expectedLangVariant = 0 ;
break ;
2012-08-26 23:33:46 +02:00
}
2012-09-26 04:17:31 +02:00
2012-08-26 23:33:46 +02:00
int numVariant = in . readUint16BE ( ) ;
2012-09-28 10:50:20 +02:00
if ( expectedLangVariant > numVariant - 1 ) {
2012-08-26 23:33:46 +02:00
msg = Common : : String : : format ( " Font variant not present in 'tony.dat'. Get it from the ScummVM website " ) ;
GUIErrorMessage ( msg ) ;
warning ( " %s " , msg . c_str ( ) ) ;
2012-09-26 04:17:31 +02:00
2012-08-26 23:33:46 +02:00
return false ;
}
2012-09-26 04:17:31 +02:00
2012-08-26 23:33:46 +02:00
in . seek ( in . pos ( ) + ( 2 * 256 * 8 * expectedLangVariant ) ) ;
for ( int i = 0 ; i < 256 ; i + + ) {
_cTableDialog [ i ] = in . readSint16BE ( ) ;
_lTableDialog [ i ] = in . readSint16BE ( ) ;
_cTableMacc [ i ] = in . readSint16BE ( ) ;
_lTableMacc [ i ] = in . readSint16BE ( ) ;
_cTableCred [ i ] = in . readSint16BE ( ) ;
_lTableCred [ i ] = in . readSint16BE ( ) ;
_cTableObj [ i ] = in . readSint16BE ( ) ;
_lTableObj [ i ] = in . readSint16BE ( ) ;
}
return true ;
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : initCustomFunctionMap ( ) {
INIT_CUSTOM_FUNCTION ( _funcList , _funcListStrings ) ;
2012-05-06 12:21:29 +10:00
}
2012-04-26 09:43:55 +10:00
/**
* Display an error message
*/
void TonyEngine : : GUIError ( const Common : : String & msg ) {
GUIErrorMessage ( msg ) ;
}
2012-06-19 20:50:48 +10:00
void TonyEngine : : playMusic ( int nChannel , const Common : : String & fname , int nFX , bool bLoop , int nSync ) {
2012-08-28 23:05:48 +02:00
if ( nChannel < 4 ) {
2012-06-08 08:44:14 +02:00
if ( GLOBALS . _flipflop )
2012-05-11 23:23:05 +10:00
nChannel = nChannel + 1 ;
2012-08-28 23:05:48 +02:00
}
2012-05-21 23:53:13 +02:00
2012-05-11 23:23:05 +10:00
switch ( nFX ) {
case 0 :
case 1 :
case 2 :
2012-06-16 11:32:50 +02:00
_stream [ nChannel ] - > stop ( ) ;
_stream [ nChannel ] - > unloadFile ( ) ;
2012-05-11 23:23:05 +10:00
break ;
case 22 :
break ;
}
2012-05-21 23:53:13 +02:00
if ( nFX = = 22 ) { // Sync a tempo
2012-06-19 20:50:48 +10:00
GLOBALS . _curChannel = nChannel ;
GLOBALS . _nextLoop = bLoop ;
GLOBALS . _nextSync = nSync ;
2012-06-19 22:37:56 +10:00
GLOBALS . _nextMusic = fname ;
2012-06-19 20:50:48 +10:00
if ( GLOBALS . _flipflop )
GLOBALS . _nextChannel = nChannel - 1 ;
2012-05-11 23:23:05 +10:00
else
2012-06-19 20:50:48 +10:00
GLOBALS . _nextChannel = nChannel + 1 ;
2012-06-19 22:37:56 +10:00
uint32 hThread = CoroScheduler . createProcess ( doNextMusic , NULL , 0 ) ;
2012-06-19 20:50:48 +10:00
assert ( hThread ! = CORO_INVALID_PID_VALUE ) ;
2012-08-31 23:08:02 +02:00
} else if ( nFX = = 44 ) { // Change the channel and let the first finish
2012-06-19 20:50:48 +10:00
if ( GLOBALS . _flipflop )
GLOBALS . _nextChannel = nChannel - 1 ;
2012-05-11 23:23:05 +10:00
else
2012-06-19 20:50:48 +10:00
GLOBALS . _nextChannel = nChannel + 1 ;
2012-05-11 23:23:05 +10:00
2012-06-19 20:50:48 +10:00
_stream [ GLOBALS . _nextChannel ] - > stop ( ) ;
_stream [ GLOBALS . _nextChannel ] - > unloadFile ( ) ;
2012-05-12 20:49:36 +10:00
if ( ! getIsDemo ( ) ) {
2015-12-31 14:48:38 +01:00
if ( ! _stream [ GLOBALS . _nextChannel ] - > loadFile ( fname , nSync ) )
2012-09-25 17:33:49 +02:00
error ( " failed to open music file '%s' " , fname . c_str ( ) ) ;
2012-05-12 20:49:36 +10:00
} else {
2015-12-31 14:48:38 +01:00
_stream [ GLOBALS . _nextChannel ] - > loadFile ( fname , nSync ) ;
2012-05-12 20:49:36 +10:00
}
2012-06-19 20:50:48 +10:00
_stream [ GLOBALS . _nextChannel ] - > setLoop ( bLoop ) ;
_stream [ GLOBALS . _nextChannel ] - > play ( ) ;
2012-05-11 23:23:05 +10:00
2012-06-19 20:50:48 +10:00
GLOBALS . _flipflop = 1 - GLOBALS . _flipflop ;
2012-05-21 23:53:13 +02:00
} else {
2012-05-12 20:49:36 +10:00
if ( ! getIsDemo ( ) ) {
2015-12-31 14:48:38 +01:00
if ( ! _stream [ nChannel ] - > loadFile ( fname , nSync ) )
2012-09-25 17:33:49 +02:00
error ( " failed to open music file '%s' " , fname . c_str ( ) ) ;
2012-05-12 20:49:36 +10:00
} else {
2015-12-31 14:48:38 +01:00
_stream [ nChannel ] - > loadFile ( fname , nSync ) ;
2012-05-12 20:49:36 +10:00
}
2012-06-19 20:50:48 +10:00
_stream [ nChannel ] - > setLoop ( bLoop ) ;
_stream [ nChannel ] - > play ( ) ;
}
}
void TonyEngine : : doNextMusic ( CORO_PARAM , const void * param ) {
CORO_BEGIN_CONTEXT ;
Common : : String fn ;
CORO_END_CONTEXT ( _ctx ) ;
2012-08-22 14:00:46 +02:00
FPStream * * streams = g_vm - > _stream ;
2012-06-19 20:50:48 +10:00
CORO_BEGIN_CODE ( _ctx ) ;
2012-08-22 14:00:46 +02:00
if ( ! g_vm - > getIsDemo ( ) ) {
2015-12-31 14:48:38 +01:00
if ( ! streams [ GLOBALS . _nextChannel ] - > loadFile ( GLOBALS . _nextMusic , GLOBALS . _nextSync ) )
2012-09-25 17:33:49 +02:00
error ( " failed to open next music file '%s' " , GLOBALS . _nextMusic . c_str ( ) ) ;
2012-06-19 20:50:48 +10:00
} else {
2015-12-31 14:48:38 +01:00
streams [ GLOBALS . _nextChannel ] - > loadFile ( GLOBALS . _nextMusic , GLOBALS . _nextSync ) ;
2012-05-11 23:23:05 +10:00
}
2012-06-19 20:50:48 +10:00
streams [ GLOBALS . _nextChannel ] - > setLoop ( GLOBALS . _nextLoop ) ;
2012-06-20 17:58:01 +02:00
//streams[GLOBALS._nextChannel]->prefetch();
2012-06-19 20:50:48 +10:00
streams [ GLOBALS . _curChannel ] - > waitForSync ( streams [ GLOBALS . _nextChannel ] ) ;
streams [ GLOBALS . _curChannel ] - > unloadFile ( ) ;
GLOBALS . _flipflop = 1 - GLOBALS . _flipflop ;
CORO_END_CODE ;
2012-04-30 23:16:19 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : playSFX ( int nChannel , int nFX ) {
if ( _sfx [ nChannel ] = = NULL )
2012-05-04 00:11:38 +10:00
return ;
switch ( nFX ) {
case 0 :
2012-06-16 11:32:50 +02:00
_sfx [ nChannel ] - > setLoop ( false ) ;
2012-05-04 00:11:38 +10:00
break ;
case 1 :
2012-06-16 11:32:50 +02:00
_sfx [ nChannel ] - > setLoop ( true ) ;
2012-05-04 00:11:38 +10:00
break ;
}
2012-06-16 11:32:50 +02:00
_sfx [ nChannel ] - > play ( ) ;
2012-04-30 23:16:19 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : stopMusic ( int nChannel ) {
2012-05-11 23:23:05 +10:00
if ( nChannel < 4 )
2012-06-16 11:32:50 +02:00
_stream [ nChannel + GLOBALS . _flipflop ] - > stop ( ) ;
2012-05-11 23:23:05 +10:00
else
2012-06-16 11:32:50 +02:00
_stream [ nChannel ] - > stop ( ) ;
2012-04-30 23:16:19 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : stopSFX ( int nChannel ) {
2012-06-16 11:32:50 +02:00
_sfx [ nChannel ] - > stop ( ) ;
2012-04-30 23:16:19 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : playUtilSFX ( int nChannel , int nFX ) {
if ( _utilSfx [ nChannel ] = = NULL )
2012-05-11 23:23:05 +10:00
return ;
switch ( nFX ) {
case 0 :
2012-06-16 11:32:50 +02:00
_utilSfx [ nChannel ] - > setLoop ( false ) ;
2012-05-11 23:23:05 +10:00
break ;
case 1 :
2012-06-16 11:32:50 +02:00
_utilSfx [ nChannel ] - > setLoop ( true ) ;
2012-05-11 23:23:05 +10:00
break ;
}
2012-06-16 11:32:50 +02:00
_utilSfx [ nChannel ] - > setVolume ( 52 ) ;
_utilSfx [ nChannel ] - > play ( ) ;
2012-04-30 23:16:19 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : stopUtilSFX ( int nChannel ) {
2012-06-16 11:32:50 +02:00
_utilSfx [ nChannel ] - > stop ( ) ;
2012-04-30 23:16:19 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : preloadSFX ( int nChannel , const char * fn ) {
if ( _sfx [ nChannel ] ! = NULL ) {
2012-06-16 11:32:50 +02:00
_sfx [ nChannel ] - > stop ( ) ;
_sfx [ nChannel ] - > release ( ) ;
2012-06-04 23:45:36 +02:00
_sfx [ nChannel ] = NULL ;
2012-05-04 00:11:38 +10:00
}
2012-06-16 11:32:50 +02:00
_theSound . createSfx ( & _sfx [ nChannel ] ) ;
2012-05-04 00:11:38 +10:00
2015-12-31 14:41:18 +01:00
_sfx [ nChannel ] - > loadFile ( fn ) ;
2012-04-30 23:16:19 +10:00
}
2012-06-16 11:32:50 +02:00
FPSfx * TonyEngine : : createSFX ( Common : : SeekableReadStream * stream ) {
FPSfx * sfx ;
2012-05-21 23:53:13 +02:00
2012-06-16 11:32:50 +02:00
_theSound . createSfx ( & sfx ) ;
2012-06-09 18:09:54 -04:00
sfx - > loadWave ( stream ) ;
2012-05-04 00:11:38 +10:00
return sfx ;
2012-04-30 23:16:19 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : preloadUtilSFX ( int nChannel , const char * fn ) {
2012-08-25 12:56:02 +02:00
if ( _utilSfx [ nChannel ] ! = NULL ) {
_utilSfx [ nChannel ] - > stop ( ) ;
_utilSfx [ nChannel ] - > release ( ) ;
_utilSfx [ nChannel ] = NULL ;
}
_theSound . createSfx ( & _utilSfx [ nChannel ] ) ;
2015-12-31 14:41:18 +01:00
_utilSfx [ nChannel ] - > loadFile ( fn ) ;
2012-08-25 12:56:02 +02:00
_utilSfx [ nChannel ] - > setVolume ( 63 ) ;
2012-04-30 23:16:19 +10:00
}
2012-06-18 08:24:33 +02:00
void TonyEngine : : unloadAllSFX ( ) {
2012-08-25 12:56:02 +02:00
for ( int i = 0 ; i < MAX_SFX_CHANNELS ; i + + ) {
if ( _sfx [ i ] ! = NULL ) {
_sfx [ i ] - > stop ( ) ;
_sfx [ i ] - > release ( ) ;
_sfx [ i ] = NULL ;
}
}
2012-04-30 23:16:19 +10:00
}
2012-06-18 08:24:33 +02:00
void TonyEngine : : unloadAllUtilSFX ( ) {
2012-08-25 12:56:02 +02:00
for ( int i = 0 ; i < MAX_SFX_CHANNELS ; i + + ) {
if ( _utilSfx [ i ] ! = NULL ) {
_utilSfx [ i ] - > stop ( ) ;
_utilSfx [ i ] - > release ( ) ;
_utilSfx [ i ] = NULL ;
}
}
2012-04-30 23:16:19 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : initMusic ( ) {
2012-05-04 00:11:38 +10:00
int i ;
2012-08-29 09:12:53 +02:00
_theSound . init ( ) ;
2012-06-16 11:32:50 +02:00
_theSound . setMasterVolume ( 63 ) ;
2012-05-21 23:53:13 +02:00
2012-05-04 00:11:38 +10:00
for ( i = 0 ; i < 6 ; i + + )
2012-06-16 11:32:50 +02:00
_theSound . createStream ( & _stream [ i ] ) ;
2012-05-04 00:11:38 +10:00
for ( i = 0 ; i < MAX_SFX_CHANNELS ; i + + ) {
2012-06-04 23:45:36 +02:00
_sfx [ i ] = _utilSfx [ i ] = NULL ;
2012-05-04 00:11:38 +10:00
}
2012-05-20 13:54:59 +10:00
// Preload sound effects
2012-06-04 23:45:36 +02:00
preloadUtilSFX ( 0 , " U01.ADP " ) ; // Reversed!!
preloadUtilSFX ( 1 , " U02.ADP " ) ;
2012-06-11 12:20:12 +10:00
// Start check processes for sound
2012-06-16 11:32:50 +02:00
CoroScheduler . createProcess ( FPSfx : : soundCheckProcess , NULL ) ;
2012-04-29 11:23:02 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : closeMusic ( ) {
2012-05-04 00:11:38 +10:00
for ( int i = 0 ; i < 6 ; i + + ) {
2012-06-16 11:32:50 +02:00
_stream [ i ] - > stop ( ) ;
_stream [ i ] - > unloadFile ( ) ;
_stream [ i ] - > release ( ) ;
2012-05-04 00:11:38 +10:00
}
2012-06-04 23:45:36 +02:00
unloadAllSFX ( ) ;
unloadAllUtilSFX ( ) ;
2012-04-29 11:23:02 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : pauseSound ( bool bPause ) {
2012-08-28 20:25:48 +02:00
_theEngine . pauseSound ( bPause ) ;
for ( uint i = 0 ; i < 6 ; i + + )
if ( _stream [ i ] )
2012-09-08 09:59:56 +02:00
_stream [ i ] - > setPause ( bPause ) ;
2012-08-28 20:25:48 +02:00
for ( uint i = 0 ; i < MAX_SFX_CHANNELS ; i + + ) {
if ( _sfx [ i ] )
2012-09-08 09:59:56 +02:00
_sfx [ i ] - > setPause ( bPause ) ;
2012-08-28 20:25:48 +02:00
if ( _utilSfx [ i ] )
2012-09-08 09:59:56 +02:00
_utilSfx [ i ] - > setPause ( bPause ) ;
2012-08-28 20:25:48 +02:00
}
2012-04-29 11:23:02 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : setMusicVolume ( int nChannel , int volume ) {
2012-08-28 20:25:48 +02:00
_stream [ nChannel + GLOBALS . _flipflop ] - > setVolume ( volume ) ;
2012-04-29 11:23:02 +10:00
}
2012-06-04 23:45:36 +02:00
int TonyEngine : : getMusicVolume ( int nChannel ) {
2012-08-28 20:25:48 +02:00
int volume ;
_stream [ nChannel + GLOBALS . _flipflop ] - > getVolume ( & volume ) ;
return volume ;
2012-04-29 11:23:02 +10:00
}
2012-06-04 23:45:36 +02:00
Common : : String TonyEngine : : getSaveStateFileName ( int n ) {
2012-05-12 21:54:37 +10:00
return Common : : String : : format ( " tony.%03d " , n ) ;
2012-05-03 22:49:30 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : autoSave ( CORO_PARAM ) {
2012-05-09 00:42:27 +10:00
CORO_BEGIN_CONTEXT ;
2012-05-21 23:53:13 +02:00
Common : : String buf ;
2012-05-09 00:42:27 +10:00
CORO_END_CONTEXT ( _ctx ) ;
CORO_BEGIN_CODE ( _ctx ) ;
2012-05-03 22:49:30 +10:00
2012-06-04 23:45:36 +02:00
grabThumbnail ( ) ;
2012-08-28 22:28:44 +02:00
CORO_INVOKE_2 ( CoroScheduler . waitForSingleObject , g_vm - > _hEndOfFrame , CORO_INFINITE ) ;
CORO_INVOKE_2 ( CoroScheduler . waitForSingleObject , g_vm - > _hEndOfFrame , CORO_INFINITE ) ;
2012-06-04 23:45:36 +02:00
_ctx - > buf = getSaveStateFileName ( 0 ) ;
2012-06-05 01:04:53 +02:00
_theEngine . saveState ( _ctx - > buf , ( byte * ) _curThumbnail , " Autosave " ) ;
2012-05-09 00:42:27 +10:00
CORO_END_CODE ;
2012-05-03 22:49:30 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : saveState ( int n , const char * name ) {
Common : : String buf = getSaveStateFileName ( n ) ;
2012-06-05 01:04:53 +02:00
_theEngine . saveState ( buf . c_str ( ) , ( byte * ) _curThumbnail , name ) ;
2012-05-03 22:49:30 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : loadState ( CORO_PARAM , int n ) {
2012-05-09 23:15:41 +10:00
CORO_BEGIN_CONTEXT ;
2012-05-21 23:53:13 +02:00
Common : : String buf ;
2012-05-09 23:15:41 +10:00
CORO_END_CONTEXT ( _ctx ) ;
2012-05-03 22:49:30 +10:00
2012-05-09 23:15:41 +10:00
CORO_BEGIN_CODE ( _ctx ) ;
2012-06-04 23:45:36 +02:00
_ctx - > buf = getSaveStateFileName ( n ) ;
2012-06-05 01:04:53 +02:00
CORO_INVOKE_1 ( _theEngine . loadState , _ctx - > buf . c_str ( ) ) ;
2012-05-09 23:15:41 +10:00
CORO_END_CODE ;
2012-05-03 22:49:30 +10:00
}
2012-06-04 23:45:36 +02:00
bool TonyEngine : : openVoiceDatabase ( ) {
2012-04-29 11:23:02 +10:00
// Open the voices database
2016-01-04 14:07:56 +01:00
if ( ! _vdbFP . open ( " voices.vdb " ) )
if ( ! _vdbFP . open ( " voices.mdb " ) )
if ( ! _vdbFP . open ( " voices.odb " ) )
if ( ! _vdbFP . open ( " voices.fdb " ) )
return false ;
2012-04-29 11:23:02 +10:00
_vdbFP . seek ( - 8 , SEEK_END ) ;
2016-01-04 13:53:11 +01:00
uint32 numfiles = _vdbFP . readUint32LE ( ) ;
2016-01-04 14:07:56 +01:00
int32 id = _vdbFP . readUint32BE ( ) ;
2012-04-29 11:23:02 +10:00
2016-01-04 14:07:56 +01:00
if ( id = = MKTAG ( ' V ' , ' D ' , ' B ' , ' 1 ' ) )
_vdbCodec = FPCODEC_ADPCM ;
else if ( id = = MKTAG ( ' M ' , ' D ' , ' B ' , ' 1 ' ) )
_vdbCodec = FPCODEC_MP3 ;
else if ( id = = MKTAG ( ' O ' , ' D ' , ' B ' , ' 1 ' ) )
_vdbCodec = FPCODEC_OGG ;
else if ( id = = MKTAG ( ' F ' , ' D ' , ' B ' , ' 1 ' ) )
_vdbCodec = FPCODEC_FLAC ;
else {
_vdbFP . close ( ) ;
2012-04-29 11:23:02 +10:00
return false ;
}
2016-01-04 14:07:56 +01:00
2012-04-29 11:23:02 +10:00
// Read in the index
_vdbFP . seek ( - 8 - ( numfiles * VOICE_HEADER_SIZE ) , SEEK_END ) ;
for ( uint32 i = 0 ; i < numfiles ; + + i ) {
VoiceHeader vh ;
2012-06-04 23:45:36 +02:00
vh . _offset = _vdbFP . readUint32LE ( ) ;
vh . _code = _vdbFP . readUint32LE ( ) ;
vh . _parts = _vdbFP . readUint32LE ( ) ;
2012-04-29 11:23:02 +10:00
_voices . push_back ( vh ) ;
}
return true ;
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : closeVoiceDatabase ( ) {
2012-04-29 11:23:02 +10:00
if ( _vdbFP . isOpen ( ) )
_vdbFP . close ( ) ;
if ( _voices . size ( ) > 0 )
_voices . clear ( ) ;
}
2012-06-18 08:24:33 +02:00
void TonyEngine : : grabThumbnail ( ) {
2012-06-06 08:04:33 +02:00
_window . grabThumbnail ( _curThumbnail ) ;
2012-04-30 23:16:19 +10:00
}
2012-09-01 01:05:22 +02:00
uint16 * TonyEngine : : getThumbnail ( ) {
return _curThumbnail ;
}
void TonyEngine : : quitGame ( ) {
_bQuitNow = true ;
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : openInitLoadMenu ( CORO_PARAM ) {
2012-06-05 01:04:53 +02:00
_theEngine . openOptionScreen ( coroParam , 1 ) ;
2012-05-03 22:49:30 +10:00
}
2012-06-04 23:45:36 +02:00
void TonyEngine : : openInitOptions ( CORO_PARAM ) {
2012-06-05 01:04:53 +02:00
_theEngine . openOptionScreen ( coroParam , 2 ) ;
2012-05-03 22:49:30 +10:00
}
2012-05-09 23:15:41 +10:00
/**
* Main process for playing the game .
*
2012-05-21 23:53:13 +02:00
* @ remarks This needs to be in a separate process , since there are some things that can briefly
2012-05-09 23:15:41 +10:00
* block the execution of process . For now , all ScummVm event handling is dispatched to within the context of this
* process . If it ever proves a problem , we may have to look into whether it ' s feasible to have it still remain
* in the outer ' main ' process .
*/
2012-06-04 23:45:36 +02:00
void TonyEngine : : playProcess ( CORO_PARAM , const void * param ) {
2012-05-09 23:15:41 +10:00
CORO_BEGIN_CONTEXT ;
2012-05-21 23:53:13 +02:00
Common : : String fn ;
2012-05-09 23:15:41 +10:00
CORO_END_CONTEXT ( _ctx ) ;
2012-05-05 22:33:13 +10:00
2012-05-16 00:05:48 +10:00
2012-05-09 23:15:41 +10:00
CORO_BEGIN_CODE ( _ctx ) ;
2012-05-05 20:54:21 +10:00
2012-05-16 00:05:48 +10:00
// Game loop. We rely on the outer main process to detect if a shutdown is required,
2012-05-09 23:15:41 +10:00
// and kill the scheudler and all the processes, including this one
for ( ; ; ) {
2012-05-16 00:05:48 +10:00
// If a savegame needs to be loaded, then do so
2012-08-22 14:00:46 +02:00
if ( g_vm - > _loadSlotNumber ! = - 1 & & GLOBALS . _gfxEngine ! = NULL ) {
_ctx - > fn = getSaveStateFileName ( g_vm - > _loadSlotNumber ) ;
2012-06-10 22:02:31 +02:00
CORO_INVOKE_1 ( GLOBALS . _gfxEngine - > loadState , _ctx - > fn ) ;
2012-08-22 14:00:46 +02:00
g_vm - > _loadSlotNumber = - 1 ;
2012-05-16 00:05:48 +10:00
}
2012-05-09 23:15:41 +10:00
// Wait for the next frame
2012-05-11 23:15:59 +10:00
CORO_INVOKE_1 ( CoroScheduler . sleep , 50 ) ;
2012-05-06 12:21:29 +10:00
2012-05-21 23:53:13 +02:00
// Call the engine to handle the next frame
2012-08-22 14:00:46 +02:00
CORO_INVOKE_1 ( g_vm - > _theEngine . doFrame , g_vm - > _bDrawLocation ) ;
2012-05-01 23:44:02 +10:00
2012-05-05 22:33:13 +10:00
// Warns that a frame is finished
2012-08-22 14:00:46 +02:00
CoroScheduler . pulseEvent ( g_vm - > _hEndOfFrame ) ;
2012-05-01 23:44:02 +10:00
2012-05-05 22:33:13 +10:00
// Handle drawing the frame
2012-08-22 14:00:46 +02:00
if ( ! g_vm - > _bPaused ) {
if ( ! g_vm - > _theEngine . _bWiping )
g_vm - > _window . getNewFrame ( g_vm - > _theEngine , NULL ) ;
2012-05-01 23:44:02 +10:00
else
2012-08-22 14:00:46 +02:00
g_vm - > _window . getNewFrame ( g_vm - > _theEngine , & g_vm - > _theEngine . _rcWipeEllipse ) ;
2012-05-01 23:44:02 +10:00
}
2012-05-05 22:33:13 +10:00
// Paint the frame onto the screen
2012-08-22 14:00:46 +02:00
g_vm - > _window . repaint ( ) ;
2012-05-22 00:29:27 +10:00
// Signal the ScummVM debugger
2012-08-22 14:00:46 +02:00
g_vm - > _debugger - > onFrame ( ) ;
2012-05-09 23:15:41 +10:00
}
CORO_END_CODE ;
}
/**
* Play the game
*/
2012-06-18 08:24:33 +02:00
void TonyEngine : : play ( ) {
2012-05-09 23:15:41 +10:00
// Create the game player process
2012-06-04 23:45:36 +02:00
CoroScheduler . createProcess ( playProcess , NULL ) ;
2012-05-09 23:15:41 +10:00
// Loop through calling the scheduler until it's time for the game to quit
2012-06-04 23:45:36 +02:00
while ( ! shouldQuit ( ) & & ! _bQuitNow ) {
2012-05-09 23:15:41 +10:00
// Delay for a brief amount
g_system - > delayMillis ( 10 ) ;
// Call any scheduled processes
2012-05-11 23:15:59 +10:00
CoroScheduler . schedule ( ) ;
2012-05-05 22:33:13 +10:00
}
2012-05-01 23:44:02 +10:00
}
2012-06-18 08:24:33 +02:00
void TonyEngine : : close ( ) {
2012-06-04 23:45:36 +02:00
closeMusic ( ) ;
CoroScheduler . closeEvent ( _hEndOfFrame ) ;
2012-06-07 07:58:01 +02:00
_theBoxes . close ( ) ;
2012-06-05 01:04:53 +02:00
_theEngine . close ( ) ;
2012-06-06 08:04:33 +02:00
_window . close ( ) ;
2012-06-09 13:05:48 +10:00
mpalFree ( ) ;
2012-08-31 23:08:02 +02:00
freeMpc ( ) ;
2012-06-04 23:45:36 +02:00
delete [ ] _curThumbnail ;
2012-05-01 23:44:02 +10:00
}
2012-06-18 08:24:33 +02:00
void TonyEngine : : freezeTime ( ) {
2012-06-04 23:45:36 +02:00
_bTimeFreezed = true ;
_nTimeFreezed = getTime ( ) - _startTime ;
2012-05-03 22:49:30 +10:00
}
2012-06-18 08:24:33 +02:00
void TonyEngine : : unfreezeTime ( ) {
2012-06-04 23:45:36 +02:00
_bTimeFreezed = false ;
2012-05-03 22:49:30 +10:00
}
/**
* Returns the millisecond timer
*/
2012-06-04 23:45:36 +02:00
uint32 TonyEngine : : getTime ( ) {
2012-05-03 22:49:30 +10:00
return g_system - > getMillis ( ) ;
}
2012-05-16 00:05:48 +10:00
bool TonyEngine : : canLoadGameStateCurrently ( ) {
2012-06-10 22:02:31 +02:00
return GLOBALS . _gfxEngine ! = NULL & & GLOBALS . _gfxEngine - > canLoadSave ( ) ;
2012-05-16 00:05:48 +10:00
}
2012-11-12 00:39:20 +00:00
2012-05-16 00:05:48 +10:00
bool TonyEngine : : canSaveGameStateCurrently ( ) {
2012-06-10 22:02:31 +02:00
return GLOBALS . _gfxEngine ! = NULL & & GLOBALS . _gfxEngine - > canLoadSave ( ) ;
2012-05-16 00:05:48 +10:00
}
Common : : Error TonyEngine : : loadGameState ( int slot ) {
_loadSlotNumber = slot ;
return Common : : kNoError ;
}
Common : : Error TonyEngine : : saveGameState ( int slot , const Common : : String & desc ) {
2012-06-10 22:02:31 +02:00
if ( ! GLOBALS . _gfxEngine )
2012-05-16 00:05:48 +10:00
return Common : : kUnknownError ;
2012-06-16 10:57:35 +10:00
RMGfxTargetBuffer & bigBuf = * GLOBALS . _gfxEngine ;
2012-05-16 00:05:48 +10:00
RMSnapshot s ;
2012-06-16 10:57:35 +10:00
s . grabScreenshot ( bigBuf , 4 , _curThumbnail ) ;
2012-05-16 00:05:48 +10:00
2012-06-10 22:02:31 +02:00
GLOBALS . _gfxEngine - > saveState ( getSaveStateFileName ( slot ) , ( byte * ) _curThumbnail , desc ) ;
2012-05-16 00:05:48 +10:00
return Common : : kNoError ;
}
2012-06-17 17:04:10 +10:00
void TonyEngine : : syncSoundSettings ( ) {
Engine : : syncSoundSettings ( ) ;
GLOBALS . _bCfgDubbing = ! ConfMan . getBool ( " mute " ) & & ! ConfMan . getBool ( " speech_mute " ) ;
GLOBALS . _bCfgSFX = ! ConfMan . getBool ( " mute " ) & & ! ConfMan . getBool ( " sfx_mute " ) ;
GLOBALS . _bCfgMusic = ! ConfMan . getBool ( " mute " ) & & ! ConfMan . getBool ( " music_mute " ) ;
GLOBALS . _nCfgDubbingVolume = ConfMan . getInt ( " speech_volume " ) * 10 / 256 ;
GLOBALS . _nCfgSFXVolume = ConfMan . getInt ( " sfx_volume " ) * 10 / 256 ;
GLOBALS . _nCfgMusicVolume = ConfMan . getInt ( " music_volume " ) * 10 / 256 ;
GLOBALS . _bShowSubtitles = ConfMan . getBool ( " subtitles " ) ;
GLOBALS . _nCfgTextSpeed = ConfMan . getInt ( " talkspeed " ) * 10 / 256 ;
}
void TonyEngine : : saveSoundSettings ( ) {
2012-09-24 22:05:28 +02:00
ConfMan . setBool ( " speech_mute " , ! GLOBALS . _bCfgDubbing ) ;
ConfMan . setBool ( " sfx_mute " , ! GLOBALS . _bCfgSFX ) ;
ConfMan . setBool ( " music_mute " , ! GLOBALS . _bCfgMusic ) ;
2012-06-17 17:04:10 +10:00
ConfMan . setInt ( " speech_volume " , GLOBALS . _nCfgDubbingVolume * 256 / 10 ) ;
ConfMan . setInt ( " sfx_volume " , GLOBALS . _nCfgSFXVolume * 256 / 10 ) ;
ConfMan . setInt ( " music_volume " , GLOBALS . _nCfgMusicVolume * 256 / 10 ) ;
ConfMan . setBool ( " subtitles " , GLOBALS . _bShowSubtitles ) ;
2012-08-22 21:52:22 +02:00
ConfMan . setInt ( " talkspeed " , GLOBALS . _nCfgTextSpeed * 256 / 10 ) ;
2012-06-17 17:04:10 +10:00
}
2012-09-01 01:05:22 +02:00
void TonyEngine : : showLocation ( ) {
_bDrawLocation = true ;
}
void TonyEngine : : hideLocation ( ) {
_bDrawLocation = false ;
}
2012-04-25 12:49:49 +10:00
} // End of namespace Tony