2017-05-31 18:49:03 +02: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 .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
*/
# include "common/config-manager.h"
# include "common/debug.h"
# include "common/debug-channels.h"
2017-08-29 01:22:53 +02:00
# include "common/endian.h"
2017-05-31 18:49:03 +02:00
# include "common/error.h"
2017-06-03 22:58:42 +02:00
# include "common/events.h"
2017-05-31 18:49:03 +02:00
# include "common/file.h"
# include "common/fs.h"
2017-08-29 01:22:53 +02:00
# include "common/memstream.h"
# include "common/savefile.h"
2017-06-03 22:58:42 +02:00
# include "common/str.h"
# include "common/system.h"
2017-09-30 23:26:06 +01:00
# include "common/translation.h"
2017-05-31 18:49:03 +02:00
# include "engines/util.h"
2017-06-03 22:58:42 +02:00
# include "graphics/cursorman.h"
# include "graphics/surface.h"
# include "graphics/screen.h"
# include "graphics/palette.h"
2017-08-29 01:22:53 +02:00
# include "graphics/thumbnail.h"
# include "gui/saveload.h"
2017-05-31 18:49:03 +02:00
2018-03-23 01:42:58 +01:00
# include "supernova/resman.h"
2018-03-25 00:07:37 +01:00
# include "supernova/screen.h"
2018-03-21 12:14:24 +01:00
# include "supernova/sound.h"
2017-05-31 18:49:03 +02:00
# include "supernova/supernova.h"
2017-07-11 05:33:46 +02:00
# include "supernova/state.h"
2017-05-31 18:49:03 +02:00
namespace Supernova {
2017-06-15 19:55:09 +02:00
ObjectType operator | ( ObjectType a , ObjectType b ) {
return static_cast < ObjectType > ( + a | + b ) ;
}
2017-06-16 10:25:41 +02:00
ObjectType operator & ( ObjectType a , ObjectType b ) {
return static_cast < ObjectType > ( + a & + b ) ;
}
2017-06-15 19:55:09 +02:00
ObjectType operator ^ ( ObjectType a , ObjectType b ) {
return static_cast < ObjectType > ( + a ^ + b ) ;
}
ObjectType & operator | = ( ObjectType & a , ObjectType b ) {
return a = a | b ;
}
2017-06-16 10:25:41 +02:00
ObjectType & operator & = ( ObjectType & a , ObjectType b ) {
return a = a & b ;
}
2017-06-15 19:55:09 +02:00
ObjectType & operator ^ = ( ObjectType & a , ObjectType b ) {
return a = a ^ b ;
}
2017-05-31 18:49:03 +02:00
SupernovaEngine : : SupernovaEngine ( OSystem * syst )
2017-09-24 17:53:01 +01:00
: Engine ( syst )
2018-03-23 02:22:10 +01:00
, _console ( nullptr )
, _gm ( nullptr )
2018-03-25 00:07:37 +01:00
, _sound ( nullptr )
, _resMan ( nullptr )
, _screen ( nullptr )
2017-09-24 17:53:01 +01:00
, _delay ( 33 )
, _textSpeed ( kTextSpeed [ 2 ] )
, _allowLoadGame ( true )
2018-03-25 00:07:37 +01:00
, _allowSaveGame ( true ) {
2017-11-07 23:54:41 +00:00
if ( ConfMan . hasKey ( " textspeed " ) )
_textSpeed = ConfMan . getInt ( " textspeed " ) ;
2017-05-31 18:49:03 +02:00
DebugMan . addDebugChannel ( kDebugGeneral , " general " , " Supernova general debug channel " ) ;
}
SupernovaEngine : : ~ SupernovaEngine ( ) {
DebugMan . clearAllDebugChannels ( ) ;
2017-06-15 22:16:48 +02:00
2017-06-03 22:58:42 +02:00
delete _console ;
2017-07-23 12:29:11 +02:00
delete _gm ;
2018-03-21 12:14:24 +01:00
delete _sound ;
2018-03-23 01:42:58 +01:00
delete _resMan ;
2018-03-25 00:07:37 +01:00
delete _screen ;
2017-05-31 18:49:03 +02:00
}
Common : : Error SupernovaEngine : : run ( ) {
2018-03-21 12:19:47 +01:00
init ( ) ;
while ( ! shouldQuit ( ) ) {
uint32 start = _system - > getMillis ( ) ;
_gm - > updateEvents ( ) ;
_gm - > executeRoom ( ) ;
_console - > onFrame ( ) ;
_system - > updateScreen ( ) ;
int end = _delay - ( _system - > getMillis ( ) - start ) ;
if ( end > 0 )
_system - > delayMillis ( end ) ;
}
_mixer - > stopAll ( ) ;
return Common : : kNoError ;
}
void SupernovaEngine : : init ( ) {
2018-01-11 01:17:51 +01:00
Graphics : : ModeList modes ;
modes . push_back ( Graphics : : Mode ( 320 , 200 ) ) ;
modes . push_back ( Graphics : : Mode ( 640 , 480 ) ) ;
initGraphicsModes ( modes ) ;
2018-03-25 00:07:37 +01:00
initGraphics ( 320 , 200 ) ;
2017-09-30 23:26:06 +01:00
Common : : Error status = loadGameStrings ( ) ;
if ( status . getCode ( ) ! = Common : : kNoError )
2018-03-21 12:19:47 +01:00
error ( " Failed reading game strings " ) ;
2017-09-30 23:26:06 +01:00
2018-03-25 01:08:26 +01:00
_resMan = new ResourceManager ( ) ;
2018-03-23 01:42:58 +01:00
_sound = new Sound ( _mixer , _resMan ) ;
2018-03-21 12:14:24 +01:00
_gm = new GameManager ( this , _sound ) ;
2018-03-25 00:07:37 +01:00
_screen = new Screen ( this , _gm , _resMan ) ;
2018-03-21 12:14:24 +01:00
_console = new Console ( this , _gm ) ;
2017-09-05 19:43:18 +01:00
setTotalPlayTime ( 0 ) ;
2017-09-04 23:04:01 +01:00
int saveSlot = ConfMan . getInt ( " save_slot " ) ;
if ( saveSlot > = 0 ) {
if ( loadGameState ( saveSlot ) . getCode ( ) ! = Common : : kNoError )
error ( " Failed to load save game from slot %i " , saveSlot ) ;
}
2017-05-31 18:49:03 +02:00
}
2017-08-27 17:10:08 +02:00
bool SupernovaEngine : : hasFeature ( EngineFeature f ) const {
switch ( f ) {
case kSupportsRTL :
return true ;
2017-08-29 01:27:07 +02:00
case kSupportsLoadingDuringRuntime :
return true ;
case kSupportsSavingDuringRuntime :
return true ;
2017-08-27 17:10:08 +02:00
default :
return false ;
}
}
2017-08-29 01:22:53 +02:00
void SupernovaEngine : : pauseEngineIntern ( bool pause ) {
_mixer - > pauseAll ( pause ) ;
2017-11-07 23:51:27 +00:00
_gm - > pauseTimer ( pause ) ;
2017-08-29 01:22:53 +02:00
}
2017-09-30 23:26:06 +01:00
Common : : Error SupernovaEngine : : loadGameStrings ( ) {
Common : : String cur_lang = ConfMan . get ( " language " ) ;
Common : : String string_id ( " TEXT " ) ;
// Note: we don't print any warning or errors here if we cannot find the file
// or the format is not as expected. We will get those warning when reading the
// strings anyway (actually the engine will even refuse to start).
Common : : File f ;
if ( ! f . open ( SUPERNOVA_DAT ) ) {
Common : : String msg = Common : : String : : format ( _ ( " Unable to locate the '%s' engine data file. " ) , SUPERNOVA_DAT ) ;
GUIErrorMessage ( msg ) ;
return Common : : kReadingFailed ;
}
// Validate the data file header
char id [ 5 ] , lang [ 5 ] ;
id [ 4 ] = lang [ 4 ] = ' \0 ' ;
f . read ( id , 3 ) ;
if ( strncmp ( id , " MSN " , 3 ) ! = 0 ) {
Common : : String msg = Common : : String : : format ( _ ( " The '%s' engine data file is corrupt. " ) , SUPERNOVA_DAT ) ;
GUIErrorMessage ( msg ) ;
return Common : : kReadingFailed ;
}
2018-03-09 11:20:47 +01:00
2017-09-30 23:26:06 +01:00
int version = f . readByte ( ) ;
if ( version ! = SUPERNOVA_DAT_VERSION ) {
Common : : String msg = Common : : String : : format (
_ ( " Incorrect version of the '%s' engine data file found. Expected %d but got %d. " ) ,
SUPERNOVA_DAT , SUPERNOVA_DAT_VERSION , version ) ;
GUIErrorMessage ( msg ) ;
return Common : : kReadingFailed ;
}
while ( ! f . eos ( ) ) {
f . read ( id , 4 ) ;
f . read ( lang , 4 ) ;
uint32 size = f . readUint32LE ( ) ;
if ( f . eos ( ) )
break ;
if ( string_id = = id & & cur_lang = = lang ) {
while ( size > 0 ) {
Common : : String s ;
char ch ;
while ( ( ch = ( char ) f . readByte ( ) ) ! = ' \0 ' )
s + = ch ;
_gameStrings . push_back ( s ) ;
size - = s . size ( ) + 1 ;
}
return Common : : kNoError ;
} else
f . skip ( size ) ;
}
Common : : Language l = Common : : parseLanguage ( cur_lang ) ;
Common : : String msg = Common : : String : : format ( _ ( " Unable to locate the text for %s language in '%s' engine data file. " ) , Common : : getLanguageDescription ( l ) , SUPERNOVA_DAT ) ;
GUIErrorMessage ( msg ) ;
return Common : : kReadingFailed ;
}
2018-03-25 00:07:37 +01:00
const Common : : String & SupernovaEngine : : getGameString ( int idx ) const {
if ( idx < 0 | | idx > = ( int ) _gameStrings . size ( ) )
return _nullString ;
return _gameStrings [ idx ] ;
}
void SupernovaEngine : : setGameString ( int idx , const Common : : String & string ) {
if ( idx < 0 )
return ;
while ( ( int ) _gameStrings . size ( ) < = idx )
_gameStrings . push_back ( Common : : String ( ) ) ;
_gameStrings [ idx ] = string ;
}
2018-03-25 04:00:05 +02:00
void SupernovaEngine : : playSound ( AudioId sample ) {
2018-03-21 12:14:24 +01:00
_sound - > play ( sample ) ;
2017-06-03 22:58:42 +02:00
}
2018-03-25 04:00:05 +02:00
void SupernovaEngine : : playSound ( MusicId index ) {
2018-03-21 12:14:24 +01:00
_sound - > play ( index ) ;
2017-06-05 16:27:06 +02:00
}
2017-11-16 02:34:51 +00:00
void SupernovaEngine : : renderImage ( int section ) {
2018-03-25 00:07:37 +01:00
_screen - > renderImage ( section ) ;
2017-11-16 02:34:51 +00:00
}
bool SupernovaEngine : : setCurrentImage ( int filenumber ) {
2018-03-25 01:14:32 +01:00
return _screen - > setCurrentImage ( filenumber ) ;
2017-06-23 19:48:26 +02:00
}
2017-06-18 21:04:23 +02:00
void SupernovaEngine : : saveScreen ( int x , int y , int width , int height ) {
2018-03-25 00:07:37 +01:00
_screen - > saveScreen ( x , y , width , height ) ;
2017-06-18 21:04:23 +02:00
}
2018-02-23 19:32:21 +01:00
void SupernovaEngine : : saveScreen ( const GuiElement & guiElement ) {
2018-03-25 00:07:37 +01:00
_screen - > saveScreen ( guiElement ) ;
2018-02-23 19:32:21 +01:00
}
2017-06-18 21:04:23 +02:00
void SupernovaEngine : : restoreScreen ( ) {
2018-03-25 00:07:37 +01:00
_screen - > restoreScreen ( ) ;
2017-06-18 21:04:23 +02:00
}
void SupernovaEngine : : renderRoom ( Room & room ) {
2018-03-25 00:07:37 +01:00
_screen - > renderRoom ( room ) ;
2017-06-03 22:58:42 +02:00
}
2018-03-25 00:07:37 +01:00
void SupernovaEngine : : renderMessage ( const char * text , MessagePosition position ) {
_screen - > renderMessage ( text , position ) ;
2017-08-04 10:42:02 +02:00
}
2018-03-25 00:07:37 +01:00
void SupernovaEngine : : renderMessage ( const Common : : String & text , MessagePosition position ) {
_screen - > renderMessage ( text , position ) ;
2017-06-08 12:15:24 +02:00
}
2017-06-07 18:34:11 +02:00
2018-03-25 06:06:56 +02:00
void SupernovaEngine : : renderMessage ( StringId stringId , MessagePosition position , Common : : String var1 , Common : : String var2 ) {
2018-03-25 00:07:37 +01:00
_screen - > renderMessage ( stringId , position , var1 , var2 ) ;
2017-06-18 18:28:01 +02:00
}
void SupernovaEngine : : removeMessage ( ) {
2018-03-25 00:07:37 +01:00
_screen - > removeMessage ( ) ;
2017-06-09 06:47:56 +02:00
}
2018-03-25 00:07:37 +01:00
void SupernovaEngine : : renderText ( const uint16 character ) {
_screen - > renderText ( character ) ;
}
2017-06-15 22:16:48 +02:00
2018-03-25 00:07:37 +01:00
void SupernovaEngine : : renderText ( const char * text ) {
_screen - > renderText ( text ) ;
}
2017-06-09 06:47:56 +02:00
2018-03-25 00:07:37 +01:00
void SupernovaEngine : : renderText ( const Common : : String & text ) {
_screen - > renderText ( text ) ;
}
2017-06-21 07:45:25 +02:00
2018-03-25 06:06:56 +02:00
void SupernovaEngine : : renderText ( StringId stringId ) {
2018-03-25 00:07:37 +01:00
_screen - > renderText ( stringId ) ;
}
void SupernovaEngine : : renderText ( const GuiElement & guiElement ) {
_screen - > renderText ( guiElement ) ;
2017-06-21 07:45:25 +02:00
}
2017-08-04 10:42:02 +02:00
void SupernovaEngine : : renderText ( const uint16 character , int x , int y , byte color ) {
2018-03-25 00:07:37 +01:00
_screen - > renderText ( character , x , y , color ) ;
2017-08-04 10:42:02 +02:00
}
2018-03-25 00:07:37 +01:00
void SupernovaEngine : : renderText ( const char * text , int x , int y , byte color ) {
_screen - > renderText ( text , x , y , color ) ;
2017-06-09 06:47:56 +02:00
}
2018-03-25 00:07:37 +01:00
void SupernovaEngine : : renderText ( const Common : : String & text , int x , int y , byte color ) {
_screen - > renderText ( text , x , y , color ) ;
2017-08-04 10:42:02 +02:00
}
2018-03-25 00:07:37 +01:00
2018-03-25 06:06:56 +02:00
void SupernovaEngine : : renderText ( StringId stringId , int x , int y , byte color ) {
2018-03-25 00:07:37 +01:00
_screen - > renderText ( stringId , x , y , color ) ;
2018-02-23 19:32:21 +01:00
}
2017-08-04 10:42:02 +02:00
2017-06-07 18:34:11 +02:00
void SupernovaEngine : : renderBox ( int x , int y , int width , int height , byte color ) {
2018-03-25 00:07:37 +01:00
_screen - > renderBox ( x , y , width , height , color ) ;
2017-06-07 18:34:11 +02:00
}
2018-02-23 19:32:21 +01:00
void SupernovaEngine : : renderBox ( const GuiElement & guiElement ) {
2018-03-25 00:07:37 +01:00
_screen - > renderBox ( guiElement ) ;
2018-02-23 19:32:21 +01:00
}
2017-06-10 00:17:19 +02:00
void SupernovaEngine : : paletteBrightness ( ) {
2018-03-25 00:07:37 +01:00
_screen - > paletteBrightness ( ) ;
2017-05-31 18:49:03 +02:00
}
2017-06-08 12:15:24 +02:00
2017-06-10 00:17:19 +02:00
void SupernovaEngine : : paletteFadeOut ( ) {
2018-03-25 00:07:37 +01:00
_screen - > paletteFadeOut ( ) ;
2017-06-10 00:17:19 +02:00
}
void SupernovaEngine : : paletteFadeIn ( ) {
2018-03-25 00:07:37 +01:00
_screen - > paletteFadeIn ( ) ;
2017-06-10 00:17:19 +02:00
}
2017-06-18 21:04:23 +02:00
void SupernovaEngine : : setColor63 ( byte value ) {
2018-03-25 00:07:37 +01:00
_screen - > setColor63 ( value ) ;
2017-06-18 21:04:23 +02:00
}
2017-11-07 23:54:41 +00:00
void SupernovaEngine : : setTextSpeed ( ) {
2018-03-25 00:07:37 +01:00
const Common : : String & textSpeedString = getGameString ( kStringTextSpeed ) ;
int stringWidth = Screen : : textWidth ( textSpeedString ) ;
int textX = ( kScreenWidth - stringWidth ) / 2 ;
2017-11-07 23:54:41 +00:00
int textY = 100 ;
stringWidth + = 4 ;
2018-03-25 00:07:37 +01:00
int boxX = stringWidth > 110 ? ( kScreenWidth - stringWidth ) / 2 : 105 ;
2017-11-07 23:54:41 +00:00
int boxY = 97 ;
int boxWidth = stringWidth > 110 ? stringWidth : 110 ;
int boxHeight = 27 ;
_gm - > animationOff ( ) ;
_gm - > saveTime ( ) ;
saveScreen ( boxX , boxY , boxWidth , boxHeight ) ;
renderBox ( boxX , boxY , boxWidth , boxHeight , kColorBlue ) ;
renderText ( textSpeedString , textX , textY , kColorWhite99 ) ; // Text speed
// Find the closest index in kTextSpeed for the current _textSpeed.
// Important note: values in kTextSpeed decrease with the index.
int speedIndex = 0 ;
while ( speedIndex < 4 & & _textSpeed < ( kTextSpeed [ speedIndex ] + kTextSpeed [ speedIndex + 1 ] ) / 2 )
+ + speedIndex ;
char nbString [ 2 ] ;
nbString [ 1 ] = 0 ;
for ( int i = 0 ; i < 5 ; + + i ) {
byte color = i = = speedIndex ? kColorWhite63 : kColorWhite35 ;
renderBox ( 110 + 21 * i , 111 , 16 , 10 , color ) ;
nbString [ 0 ] = ' 1 ' + i ;
renderText ( nbString , 115 + 21 * i , 112 , kColorWhite99 ) ;
}
do {
_gm - > getInput ( ) ;
int key = _gm - > _keyPressed ? _gm - > _key . keycode : Common : : KEYCODE_INVALID ;
if ( ! _gm - > _keyPressed & & _gm - > _mouseClicked & & _gm - > _mouseY > = 111 & & _gm - > _mouseY < 121 & & ( _gm - > _mouseX + 16 ) % 21 < 16 )
key = Common : : KEYCODE_0 - 5 + ( _gm - > _mouseX + 16 ) / 21 ;
if ( key = = Common : : KEYCODE_ESCAPE )
break ;
else if ( key > = Common : : KEYCODE_1 & & key < = Common : : KEYCODE_5 ) {
speedIndex = key - Common : : KEYCODE_1 ;
_textSpeed = kTextSpeed [ speedIndex ] ;
ConfMan . setInt ( " textspeed " , _textSpeed ) ;
break ;
}
} while ( ! shouldQuit ( ) ) ;
_gm - > resetInputState ( ) ;
restoreScreen ( ) ;
_gm - > loadTime ( ) ;
_gm - > animationOn ( ) ;
}
2018-02-23 18:25:53 +01:00
bool SupernovaEngine : : quitGameDialog ( ) {
bool quit = false ;
GuiElement guiQuitBox ;
guiQuitBox . setColor ( kColorRed , kColorWhite99 , kColorRed , kColorWhite99 ) ;
guiQuitBox . setSize ( 112 , 97 , 112 + 96 , 97 + 27 ) ;
2018-03-01 19:19:38 +01:00
guiQuitBox . setText ( getGameString ( kStringLeaveGame ) . c_str ( ) ) ;
2018-02-23 18:25:53 +01:00
guiQuitBox . setTextPosition ( guiQuitBox . left + 3 , guiQuitBox . top + 3 ) ;
GuiElement guiQuitYes ;
guiQuitYes . setColor ( kColorWhite35 , kColorWhite99 , kColorWhite35 , kColorWhite99 ) ;
guiQuitYes . setSize ( 115 , 111 , 158 , 121 ) ;
2018-03-01 19:19:38 +01:00
guiQuitYes . setText ( getGameString ( kStringYes ) . c_str ( ) ) ;
2018-02-23 18:25:53 +01:00
guiQuitYes . setTextPosition ( 132 , 112 ) ;
GuiElement guiQuitNo ;
guiQuitNo . setColor ( kColorWhite35 , kColorWhite99 , kColorWhite35 , kColorWhite99 ) ;
guiQuitNo . setSize ( 162 , 111 , 205 , 121 ) ;
2018-03-01 19:19:38 +01:00
guiQuitNo . setText ( getGameString ( kStringNo ) . c_str ( ) ) ;
2018-02-23 18:25:53 +01:00
guiQuitNo . setTextPosition ( 173 , 112 ) ;
_gm - > animationOff ( ) ;
_gm - > saveTime ( ) ;
2018-02-23 19:32:21 +01:00
saveScreen ( guiQuitBox ) ;
renderBox ( guiQuitBox ) ;
renderText ( guiQuitBox ) ;
renderBox ( guiQuitYes ) ;
renderText ( guiQuitYes ) ;
renderBox ( guiQuitNo ) ;
renderText ( guiQuitNo ) ;
2018-02-23 18:25:53 +01:00
do {
_gm - > getInput ( ) ;
if ( _gm - > _keyPressed ) {
if ( _gm - > _key . keycode = = Common : : KEYCODE_j ) {
quit = true ;
break ;
} else if ( _gm - > _key . keycode = = Common : : KEYCODE_n ) {
quit = false ;
break ;
}
}
if ( _gm - > _mouseClicked ) {
if ( guiQuitYes . contains ( _gm - > _mouseX , _gm - > _mouseY ) ) {
quit = true ;
break ;
} else if ( guiQuitNo . contains ( _gm - > _mouseX , _gm - > _mouseY ) ) {
quit = false ;
break ;
}
}
} while ( true ) ;
_gm - > resetInputState ( ) ;
restoreScreen ( ) ;
_gm - > loadTime ( ) ;
_gm - > animationOn ( ) ;
return quit ;
}
2017-06-18 21:04:23 +02:00
2017-08-29 01:27:07 +02:00
bool SupernovaEngine : : canLoadGameStateCurrently ( ) {
return _allowLoadGame ;
}
Common : : Error SupernovaEngine : : loadGameState ( int slot ) {
2017-08-30 22:37:41 +02:00
return ( loadGame ( slot ) ? Common : : kNoError : Common : : kReadingFailed ) ;
2017-08-29 01:27:07 +02:00
}
bool SupernovaEngine : : canSaveGameStateCurrently ( ) {
2017-11-17 23:13:45 +00:00
// Do not allow saving when either _allowSaveGame, _animationEnabled or _guiEnabled is false
return _allowSaveGame & & _gm - > _animationEnabled & & _gm - > _guiEnabled ;
2017-08-29 01:27:07 +02:00
}
Common : : Error SupernovaEngine : : saveGameState ( int slot , const Common : : String & desc ) {
return ( saveGame ( slot , desc ) ? Common : : kNoError : Common : : kWritingFailed ) ;
}
bool SupernovaEngine : : loadGame ( int slot ) {
2017-08-31 20:53:18 +02:00
if ( slot < 0 )
2017-08-29 01:27:07 +02:00
return false ;
2017-08-31 20:53:18 +02:00
Common : : String filename = Common : : String : : format ( " msn_save.%03d " , slot ) ;
Common : : InSaveFile * savefile = _saveFileMan - > openForLoading ( filename ) ;
2017-08-29 01:27:07 +02:00
if ( ! savefile )
return false ;
2017-09-04 22:48:50 +01:00
uint saveHeader = savefile - > readUint32LE ( ) ;
if ( saveHeader ! = SAVEGAME_HEADER ) {
warning ( " No header found in '%s' " , filename . c_str ( ) ) ;
delete savefile ;
2017-10-14 23:26:32 +02:00
return false ; //Common::kUnknownError
2017-09-04 22:48:50 +01:00
}
2018-03-09 11:20:47 +01:00
2017-09-04 22:48:50 +01:00
byte saveVersion = savefile - > readByte ( ) ;
2017-10-01 21:36:15 +01:00
// Save version 1 was used during development and is no longer supported
if ( saveVersion > SAVEGAME_VERSION | | saveVersion = = 1 ) {
2017-09-04 22:48:50 +01:00
warning ( " Save game version %i not supported " , saveVersion ) ;
delete savefile ;
2017-10-14 23:26:32 +02:00
return false ; //Common::kUnknownError;
2017-09-04 22:48:50 +01:00
}
2017-10-31 22:40:49 +00:00
// Make sure no message is displayed as this would otherwise delay the
// switch to the new location until a mouse click.
removeMessage ( ) ;
2017-08-29 01:27:07 +02:00
int descriptionSize = savefile - > readSint16LE ( ) ;
savefile - > skip ( descriptionSize ) ;
savefile - > skip ( 6 ) ;
2017-09-05 19:43:18 +01:00
setTotalPlayTime ( savefile - > readUint32LE ( ) * 1000 ) ;
2017-08-31 20:53:18 +02:00
Graphics : : skipThumbnail ( * savefile ) ;
2017-11-04 14:54:26 +00:00
_gm - > deserialize ( savefile , saveVersion ) ;
2017-08-29 01:27:07 +02:00
2017-11-17 23:13:45 +00:00
if ( saveVersion > = 5 ) {
2018-03-25 00:07:37 +01:00
_screen - > setGuiBrightness ( savefile - > readByte ( ) ) ;
_screen - > setViewportBrightness ( savefile - > readByte ( ) ) ;
2017-11-17 23:13:45 +00:00
} else {
2018-03-25 00:07:37 +01:00
_screen - > setGuiBrightness ( 255 ) ;
_screen - > setViewportBrightness ( 255 ) ;
2017-11-17 23:13:45 +00:00
}
2017-08-29 01:27:07 +02:00
delete savefile ;
return true ;
}
bool SupernovaEngine : : saveGame ( int slot , const Common : : String & description ) {
2017-08-31 20:53:18 +02:00
if ( slot < 0 )
2017-08-29 01:27:07 +02:00
return false ;
2017-08-31 20:53:18 +02:00
Common : : String filename = Common : : String : : format ( " msn_save.%03d " , slot ) ;
Common : : OutSaveFile * savefile = _saveFileMan - > openForSaving ( filename ) ;
2017-08-29 01:27:07 +02:00
if ( ! savefile )
return false ;
2018-03-09 11:20:47 +01:00
2017-09-04 22:48:50 +01:00
savefile - > writeUint32LE ( SAVEGAME_HEADER ) ;
savefile - > writeByte ( SAVEGAME_VERSION ) ;
2017-08-29 01:27:07 +02:00
TimeDate currentDate ;
_system - > getTimeAndDate ( currentDate ) ;
uint32 saveDate = ( currentDate . tm_mday & 0xFF ) < < 24 | ( ( currentDate . tm_mon + 1 ) & 0xFF ) < < 16 | ( ( currentDate . tm_year + 1900 ) & 0xFFFF ) ;
uint16 saveTime = ( currentDate . tm_hour & 0xFF ) < < 8 | ( ( currentDate . tm_min ) & 0xFF ) ;
2017-08-31 20:53:18 +02:00
savefile - > writeSint16LE ( description . size ( ) + 1 ) ;
savefile - > write ( description . c_str ( ) , description . size ( ) + 1 ) ;
2017-08-29 01:27:07 +02:00
savefile - > writeUint32LE ( saveDate ) ;
savefile - > writeUint16LE ( saveTime ) ;
2017-09-05 19:43:18 +01:00
savefile - > writeUint32LE ( getTotalPlayTime ( ) / 1000 ) ;
2017-08-31 20:53:18 +02:00
Graphics : : saveThumbnail ( * savefile ) ;
2017-08-29 01:27:07 +02:00
_gm - > serialize ( savefile ) ;
2018-03-25 00:07:37 +01:00
savefile - > writeByte ( _screen - > getGuiBrightness ( ) ) ;
savefile - > writeByte ( _screen - > getViewportBrightness ( ) ) ;
2017-11-17 23:13:45 +00:00
2017-08-29 01:27:07 +02:00
savefile - > finalize ( ) ;
delete savefile ;
return true ;
}
2017-11-17 21:04:22 +00:00
void SupernovaEngine : : errorTempSave ( bool saving ) {
2018-03-09 11:20:47 +01:00
GUIErrorMessage ( saving
2017-11-18 00:06:54 +01:00
? " Failed to save temporary game state. Make sure your save game directory is set in ScummVM and that you can write to it. "
: " Failed to load temporary game state. " ) ;
error ( " Unrecoverable error " ) ;
2017-11-17 21:04:22 +00:00
}
2017-07-11 05:33:46 +02:00
2017-06-10 00:17:19 +02:00
}