2013-05-16 21:18:09 +00: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 01:34:20 +00:00
*
2013-05-16 21:18:09 +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 .
2014-02-18 01:34:20 +00:00
*
2013-05-16 21:18:09 +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 . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
*/
# include "gui/EventRecorder.h"
2013-07-07 03:54:45 +00:00
# ifdef ENABLE_EVENTRECORDER
2013-05-16 21:18:09 +00:00
namespace Common {
DECLARE_SINGLETON ( GUI : : EventRecorder ) ;
}
# include "common/debug-channels.h"
# include "backends/timer/sdl/sdl-timer.h"
# include "backends/mixer/sdl/sdl-mixer.h"
# include "common/config-manager.h"
# include "common/md5.h"
# include "gui/gui-manager.h"
# include "gui/widget.h"
# include "gui/onscreendialog.h"
# include "common/random.h"
# include "common/savefile.h"
# include "common/textconsole.h"
# include "graphics/thumbnail.h"
# include "graphics/surface.h"
# include "graphics/scaler.h"
namespace GUI {
const int kMaxRecordsNames = 0x64 ;
const int kDefaultScreenshotPeriod = 60000 ;
uint32 readTime ( Common : : ReadStream * inFile ) {
uint32 d = inFile - > readByte ( ) ;
if ( d = = 0xff ) {
d = inFile - > readUint32LE ( ) ;
}
return d ;
}
void writeTime ( Common : : WriteStream * outFile , uint32 d ) {
//Simple RLE compression
if ( d > = 0xff ) {
outFile - > writeByte ( 0xff ) ;
outFile - > writeUint32LE ( d ) ;
} else {
outFile - > writeByte ( d ) ;
}
}
EventRecorder : : EventRecorder ( ) {
_timerManager = NULL ;
_recordMode = kPassthrough ;
_fakeMixerManager = NULL ;
_initialized = false ;
_needRedraw = false ;
_fastPlayback = false ;
2013-07-14 16:14:00 +00:00
_fakeTimer = 0 ;
_savedState = false ;
_needcontinueGame = false ;
_temporarySlot = 0 ;
_realSaveManager = 0 ;
_realMixerManager = 0 ;
2013-07-14 16:16:01 +00:00
_controlPanel = 0 ;
2013-07-14 16:14:00 +00:00
_lastMillis = 0 ;
_lastScreenshotTime = 0 ;
_screenshotPeriod = 0 ;
_playbackFile = 0 ;
2013-07-14 17:01:47 +00:00
2013-05-16 21:18:09 +00:00
DebugMan . addDebugChannel ( kDebugLevelEventRec , " EventRec " , " Event recorder debug level " ) ;
}
EventRecorder : : ~ EventRecorder ( ) {
if ( _timerManager ! = NULL ) {
delete _timerManager ;
}
}
void EventRecorder : : deinit ( ) {
if ( ! _initialized ) {
return ;
}
setFileHeader ( ) ;
_needRedraw = false ;
_initialized = false ;
_recordMode = kPassthrough ;
delete _fakeMixerManager ;
_fakeMixerManager = NULL ;
2013-07-14 16:16:01 +00:00
_controlPanel - > close ( ) ;
delete _controlPanel ;
2013-05-16 21:18:09 +00:00
debugC ( 1 , kDebugLevelEventRec , " playback:action=stopplayback " ) ;
g_system - > getEventManager ( ) - > getEventDispatcher ( ) - > unregisterSource ( this ) ;
_recordMode = kPassthrough ;
_playbackFile - > close ( ) ;
delete _playbackFile ;
switchMixer ( ) ;
switchTimerManagers ( ) ;
DebugMan . disableDebugChannel ( " EventRec " ) ;
}
void EventRecorder : : processMillis ( uint32 & millis , bool skipRecord ) {
if ( ! _initialized ) {
return ;
}
if ( skipRecord ) {
millis = _fakeTimer ;
return ;
}
if ( _recordMode = = kRecorderPlaybackPause ) {
millis = _fakeTimer ;
}
uint32 millisDelay ;
Common : : RecorderEvent timerEvent ;
switch ( _recordMode ) {
case kRecorderRecord :
updateSubsystems ( ) ;
millisDelay = millis - _lastMillis ;
_lastMillis = millis ;
_fakeTimer + = millisDelay ;
2013-07-14 16:16:01 +00:00
_controlPanel - > setReplayedTime ( _fakeTimer ) ;
2013-05-16 21:18:09 +00:00
timerEvent . recordedtype = Common : : kRecorderEventTypeTimer ;
timerEvent . time = _fakeTimer ;
_playbackFile - > writeEvent ( timerEvent ) ;
takeScreenshot ( ) ;
_timerManager - > handler ( ) ;
break ;
case kRecorderPlayback :
updateSubsystems ( ) ;
if ( _nextEvent . recordedtype = = Common : : kRecorderEventTypeTimer ) {
_fakeTimer = _nextEvent . time ;
_nextEvent = _playbackFile - > getNextEvent ( ) ;
_timerManager - > handler ( ) ;
} else {
if ( _nextEvent . type = = Common : : EVENT_RTL ) {
error ( " playback:action=stopplayback " ) ;
} else {
uint32 seconds = _fakeTimer / 1000 ;
Common : : String screenTime = Common : : String : : format ( " %.2d:%.2d:%.2d " , seconds / 3600 % 24 , seconds / 60 % 60 , seconds % 60 ) ;
error ( " playback:action=error reason= \" synchronization error \" time = %s " , screenTime . c_str ( ) ) ;
}
}
millis = _fakeTimer ;
2013-07-14 16:16:01 +00:00
_controlPanel - > setReplayedTime ( _fakeTimer ) ;
2013-05-16 21:18:09 +00:00
break ;
case kRecorderPlaybackPause :
millis = _fakeTimer ;
break ;
default :
break ;
}
}
bool EventRecorder : : processDelayMillis ( ) {
return _fastPlayback ;
}
void EventRecorder : : checkForKeyCode ( const Common : : Event & event ) {
if ( ( event . type = = Common : : EVENT_KEYDOWN ) & & ( event . kbd . flags & Common : : KBD_CTRL ) & & ( event . kbd . keycode = = Common : : KEYCODE_p ) & & ( ! event . synthetic ) ) {
togglePause ( ) ;
}
}
bool EventRecorder : : pollEvent ( Common : : Event & ev ) {
if ( ( _recordMode ! = kRecorderPlayback ) | | ! _initialized )
return false ;
2013-07-14 17:01:47 +00:00
2013-05-16 21:18:09 +00:00
if ( ( _nextEvent . recordedtype = = Common : : kRecorderEventTypeTimer ) | | ( _nextEvent . type = = Common : : EVENT_INVALID ) ) {
return false ;
}
switch ( _nextEvent . type ) {
case Common : : EVENT_MOUSEMOVE :
case Common : : EVENT_LBUTTONDOWN :
case Common : : EVENT_LBUTTONUP :
case Common : : EVENT_RBUTTONDOWN :
case Common : : EVENT_RBUTTONUP :
case Common : : EVENT_WHEELUP :
case Common : : EVENT_WHEELDOWN :
g_system - > warpMouse ( _nextEvent . mouse . x , _nextEvent . mouse . y ) ;
break ;
default :
break ;
}
ev = _nextEvent ;
_nextEvent = _playbackFile - > getNextEvent ( ) ;
return true ;
}
void EventRecorder : : switchFastMode ( ) {
if ( _recordMode = = kRecorderPlaybackPause ) {
_fastPlayback = ! _fastPlayback ;
}
}
void EventRecorder : : togglePause ( ) {
RecordMode oldState ;
switch ( _recordMode ) {
case kRecorderPlayback :
case kRecorderRecord :
oldState = _recordMode ;
_recordMode = kRecorderPlaybackPause ;
2013-07-14 16:16:01 +00:00
_controlPanel - > runModal ( ) ;
2013-05-16 21:18:09 +00:00
_recordMode = oldState ;
_initialized = true ;
break ;
case kRecorderPlaybackPause :
2013-07-14 16:16:01 +00:00
_controlPanel - > close ( ) ;
2013-05-16 21:18:09 +00:00
break ;
default :
break ;
}
}
void EventRecorder : : RegisterEventSource ( ) {
g_system - > getEventManager ( ) - > getEventDispatcher ( ) - > registerMapper ( this , false ) ;
}
uint32 EventRecorder : : getRandomSeed ( const Common : : String & name ) {
uint32 result = g_system - > getMillis ( ) ;
if ( _recordMode = = kRecorderRecord ) {
_playbackFile - > getHeader ( ) . randomSourceRecords [ name ] = result ;
} else if ( _recordMode = = kRecorderPlayback ) {
result = _playbackFile - > getHeader ( ) . randomSourceRecords [ name ] ;
}
return result ;
}
Common : : String EventRecorder : : generateRecordFileName ( const Common : : String & target ) {
Common : : String pattern ( target + " .r?? " ) ;
Common : : StringArray files = g_system - > getSavefileManager ( ) - > listSavefiles ( pattern ) ;
for ( int i = 0 ; i < kMaxRecordsNames ; + + i ) {
Common : : String recordName = Common : : String : : format ( " %s.r%02d " , target . c_str ( ) , i ) ;
if ( find ( files . begin ( ) , files . end ( ) , recordName ) ! = files . end ( ) ) {
continue ;
}
return recordName ;
}
return " " ;
}
void EventRecorder : : init ( Common : : String recordFileName , RecordMode mode ) {
_fakeMixerManager = new NullSdlMixerManager ( ) ;
_fakeMixerManager - > init ( ) ;
_fakeMixerManager - > suspendAudio ( ) ;
_fakeTimer = 0 ;
_lastMillis = g_system - > getMillis ( ) ;
_playbackFile = new Common : : PlaybackFile ( ) ;
_lastScreenshotTime = 0 ;
_recordMode = mode ;
_needcontinueGame = false ;
if ( ConfMan . hasKey ( " disable_display " ) ) {
DebugMan . enableDebugChannel ( " EventRec " ) ;
gDebugLevel = 1 ;
}
if ( _recordMode = = kRecorderPlayback ) {
debugC ( 1 , kDebugLevelEventRec , " playback:action= \" Load file \" filename=%s " , recordFileName . c_str ( ) ) ;
}
g_system - > getEventManager ( ) - > getEventDispatcher ( ) - > registerSource ( this , false ) ;
_screenshotPeriod = ConfMan . getInt ( " screenshot_period " ) ;
if ( _screenshotPeriod = = 0 ) {
_screenshotPeriod = kDefaultScreenshotPeriod ;
}
if ( ! openRecordFile ( recordFileName ) ) {
deinit ( ) ;
error ( " playback:action=error reason= \" Record file loading error \" " ) ;
return ;
}
if ( _recordMode ! = kPassthrough ) {
2013-07-14 16:16:01 +00:00
_controlPanel = new GUI : : OnScreenDialog ( _recordMode = = kRecorderRecord ) ;
2013-05-16 21:18:09 +00:00
}
if ( _recordMode = = kRecorderPlayback ) {
applyPlaybackSettings ( ) ;
_nextEvent = _playbackFile - > getNextEvent ( ) ;
}
if ( _recordMode = = kRecorderRecord ) {
getConfig ( ) ;
}
switchMixer ( ) ;
switchTimerManagers ( ) ;
_needRedraw = true ;
_initialized = true ;
}
/**
* Opens or creates file depend of recording mode .
*
* @ param id of recording or playing back game
* @ return true in case of success , false in case of error
*
*/
bool EventRecorder : : openRecordFile ( const Common : : String & fileName ) {
bool result ;
switch ( _recordMode ) {
case kRecorderRecord :
return _playbackFile - > openWrite ( fileName ) ;
case kRecorderPlayback :
_recordMode = kPassthrough ;
result = _playbackFile - > openRead ( fileName ) ;
_recordMode = kRecorderPlayback ;
return result ;
default :
return false ;
}
return true ;
}
bool EventRecorder : : checkGameHash ( const ADGameDescription * gameDesc ) {
2016-03-25 15:30:12 +00:00
if ( _playbackFile - > getHeader ( ) . hashRecords . size ( ) = = 0 ) {
2013-05-16 21:18:09 +00:00
warning ( " Engine doesn't contain description table " ) ;
return false ;
}
for ( const ADGameFileDescription * fileDesc = gameDesc - > filesDescriptions ; fileDesc - > fileName ; fileDesc + + ) {
if ( _playbackFile - > getHeader ( ) . hashRecords . find ( fileDesc - > fileName ) = = _playbackFile - > getHeader ( ) . hashRecords . end ( ) ) {
warning ( " MD5 hash for file %s not found in record file " , fileDesc - > fileName ) ;
debugC ( 1 , kDebugLevelEventRec , " playback:action= \" Check game hash \" filename=%s filehash=%s storedhash= \" \" result=different " , fileDesc - > fileName , fileDesc - > md5 ) ;
return false ;
}
if ( _playbackFile - > getHeader ( ) . hashRecords [ fileDesc - > fileName ] ! = fileDesc - > md5 ) {
warning ( " Incorrect version of game file %s. Stored MD5 is %s. MD5 of loaded game is %s " , fileDesc - > fileName , _playbackFile - > getHeader ( ) . hashRecords [ fileDesc - > fileName ] . c_str ( ) , fileDesc - > md5 ) ;
debugC ( 1 , kDebugLevelEventRec , " playback:action= \" Check game hash \" filename=%s filehash=%s storedhash=%s result=different " , fileDesc - > fileName , fileDesc - > md5 , _playbackFile - > getHeader ( ) . hashRecords [ fileDesc - > fileName ] . c_str ( ) ) ;
return false ;
}
debugC ( 1 , kDebugLevelEventRec , " playback:action= \" Check game hash \" filename=%s filehash=%s storedhash=%s result=equal " , fileDesc - > fileName , fileDesc - > md5 , _playbackFile - > getHeader ( ) . hashRecords [ fileDesc - > fileName ] . c_str ( ) ) ;
}
return true ;
}
void EventRecorder : : registerMixerManager ( SdlMixerManager * mixerManager ) {
_realMixerManager = mixerManager ;
}
void EventRecorder : : switchMixer ( ) {
if ( _recordMode = = kPassthrough ) {
_realMixerManager - > resumeAudio ( ) ;
} else {
_realMixerManager - > suspendAudio ( ) ;
_fakeMixerManager - > resumeAudio ( ) ;
}
}
SdlMixerManager * EventRecorder : : getMixerManager ( ) {
if ( _recordMode = = kPassthrough ) {
return _realMixerManager ;
} else {
return _fakeMixerManager ;
}
}
2013-08-08 01:12:02 +00:00
void EventRecorder : : getConfigFromDomain ( const Common : : ConfigManager : : Domain * domain ) {
for ( Common : : ConfigManager : : Domain : : const_iterator entry = domain - > begin ( ) ; entry ! = domain - > end ( ) ; + + entry ) {
2013-05-16 21:18:09 +00:00
_playbackFile - > getHeader ( ) . settingsRecords [ entry - > _key ] = entry - > _value ;
}
}
void EventRecorder : : getConfig ( ) {
getConfigFromDomain ( ConfMan . getDomain ( ConfMan . kApplicationDomain ) ) ;
getConfigFromDomain ( ConfMan . getActiveDomain ( ) ) ;
_playbackFile - > getHeader ( ) . settingsRecords [ " save_slot " ] = ConfMan . get ( " save_slot " ) ;
}
void EventRecorder : : applyPlaybackSettings ( ) {
2013-08-08 01:12:02 +00:00
for ( Common : : StringMap : : const_iterator i = _playbackFile - > getHeader ( ) . settingsRecords . begin ( ) ; i ! = _playbackFile - > getHeader ( ) . settingsRecords . end ( ) ; + + i ) {
2013-05-16 21:18:09 +00:00
Common : : String currentValue = ConfMan . get ( i - > _key ) ;
if ( currentValue ! = i - > _value ) {
ConfMan . set ( i - > _key , i - > _value , ConfMan . kTransientDomain ) ;
debugC ( 1 , kDebugLevelEventRec , " playback:action= \" Apply settings \" key=%s storedvalue=%s currentvalue=%s result=different " , i - > _key . c_str ( ) , i - > _value . c_str ( ) , currentValue . c_str ( ) ) ;
} else {
debugC ( 1 , kDebugLevelEventRec , " playback:action= \" Apply settings \" key=%s storedvalue=%s currentvalue=%s result=equal " , i - > _key . c_str ( ) , i - > _value . c_str ( ) , currentValue . c_str ( ) ) ;
}
}
removeDifferentEntriesInDomain ( ConfMan . getDomain ( ConfMan . kApplicationDomain ) ) ;
removeDifferentEntriesInDomain ( ConfMan . getActiveDomain ( ) ) ;
}
void EventRecorder : : removeDifferentEntriesInDomain ( Common : : ConfigManager : : Domain * domain ) {
2013-08-08 01:12:02 +00:00
for ( Common : : ConfigManager : : Domain : : const_iterator entry = domain - > begin ( ) ; entry ! = domain - > end ( ) ; + + entry ) {
2013-05-16 21:18:09 +00:00
if ( _playbackFile - > getHeader ( ) . settingsRecords . find ( entry - > _key ) = = _playbackFile - > getHeader ( ) . settingsRecords . end ( ) ) {
debugC ( 1 , kDebugLevelEventRec , " playback:action= \" Apply settings \" checksettings:key=%s storedvalue=%s currentvalue= " " result=different " , entry - > _key . c_str ( ) , entry - > _value . c_str ( ) ) ;
domain - > erase ( entry - > _key ) ;
}
}
}
DefaultTimerManager * EventRecorder : : getTimerManager ( ) {
return _timerManager ;
}
void EventRecorder : : registerTimerManager ( DefaultTimerManager * timerManager ) {
_timerManager = timerManager ;
}
void EventRecorder : : switchTimerManagers ( ) {
delete _timerManager ;
if ( _recordMode = = kPassthrough ) {
_timerManager = new SdlTimerManager ( ) ;
} else {
_timerManager = new DefaultTimerManager ( ) ;
}
}
void EventRecorder : : updateSubsystems ( ) {
if ( _recordMode = = kPassthrough ) {
return ;
}
RecordMode oldRecordMode = _recordMode ;
_recordMode = kPassthrough ;
_fakeMixerManager - > update ( ) ;
_recordMode = oldRecordMode ;
}
Common : : List < Common : : Event > EventRecorder : : mapEvent ( const Common : : Event & ev , Common : : EventSource * source ) {
if ( ( ! _initialized ) & & ( _recordMode ! = kRecorderPlaybackPause ) ) {
return DefaultEventMapper : : mapEvent ( ev , source ) ;
}
checkForKeyCode ( ev ) ;
Common : : Event evt = ev ;
evt . mouse . x = evt . mouse . x * ( g_system - > getOverlayWidth ( ) / g_system - > getWidth ( ) ) ;
evt . mouse . y = evt . mouse . y * ( g_system - > getOverlayHeight ( ) / g_system - > getHeight ( ) ) ;
switch ( _recordMode ) {
case kRecorderPlayback :
if ( ev . synthetic ! = true ) {
return Common : : List < Common : : Event > ( ) ;
}
return Common : : DefaultEventMapper : : mapEvent ( ev , source ) ;
break ;
case kRecorderRecord :
2013-07-14 16:16:01 +00:00
g_gui . processEvent ( evt , _controlPanel ) ;
if ( ( ( evt . type = = Common : : EVENT_LBUTTONDOWN ) | | ( evt . type = = Common : : EVENT_LBUTTONUP ) | | ( evt . type = = Common : : EVENT_MOUSEMOVE ) ) & & _controlPanel - > isMouseOver ( ) ) {
2013-05-16 21:18:09 +00:00
return Common : : List < Common : : Event > ( ) ;
} else {
Common : : RecorderEvent e ;
memcpy ( & e , & ev , sizeof ( ev ) ) ;
e . recordedtype = Common : : kRecorderEventTypeNormal ;
e . time = _fakeTimer ;
_playbackFile - > writeEvent ( e ) ;
return DefaultEventMapper : : mapEvent ( ev , source ) ;
}
break ;
case kRecorderPlaybackPause : {
Common : : Event dialogEvent ;
2013-07-14 16:16:01 +00:00
if ( _controlPanel - > isEditDlgVisible ( ) ) {
2013-05-16 21:18:09 +00:00
dialogEvent = ev ;
} else {
dialogEvent = evt ;
}
2013-07-14 16:16:01 +00:00
g_gui . processEvent ( dialogEvent , _controlPanel - > getActiveDlg ( ) ) ;
if ( ( ( dialogEvent . type = = Common : : EVENT_LBUTTONDOWN ) | | ( dialogEvent . type = = Common : : EVENT_LBUTTONUP ) | | ( dialogEvent . type = = Common : : EVENT_MOUSEMOVE ) ) & & _controlPanel - > isMouseOver ( ) ) {
2013-05-16 21:18:09 +00:00
return Common : : List < Common : : Event > ( ) ;
}
return Common : : DefaultEventMapper : : mapEvent ( dialogEvent , source ) ;
}
break ;
default :
return Common : : DefaultEventMapper : : mapEvent ( ev , source ) ;
}
2013-09-08 21:46:03 +00:00
return Common : : DefaultEventMapper : : mapEvent ( ev , source ) ;
2013-05-16 21:18:09 +00:00
}
void EventRecorder : : setGameMd5 ( const ADGameDescription * gameDesc ) {
for ( const ADGameFileDescription * fileDesc = gameDesc - > filesDescriptions ; fileDesc - > fileName ; fileDesc + + ) {
if ( fileDesc - > md5 ! = NULL ) {
_playbackFile - > getHeader ( ) . hashRecords [ fileDesc - > fileName ] = fileDesc - > md5 ;
}
}
}
void EventRecorder : : processGameDescription ( const ADGameDescription * desc ) {
if ( _recordMode = = kRecorderRecord ) {
setGameMd5 ( desc ) ;
}
if ( ( _recordMode = = kRecorderPlayback ) & & ! checkGameHash ( desc ) ) {
deinit ( ) ;
error ( " playback:action=error reason= \" \" " ) ;
}
}
void EventRecorder : : deleteRecord ( const Common : : String & fileName ) {
g_system - > getSavefileManager ( ) - > removeSavefile ( fileName ) ;
}
void EventRecorder : : takeScreenshot ( ) {
if ( ( _fakeTimer - _lastScreenshotTime ) > _screenshotPeriod ) {
Graphics : : Surface screen ;
uint8 md5 [ 16 ] ;
if ( grabScreenAndComputeMD5 ( screen , md5 ) ) {
_lastScreenshotTime = _fakeTimer ;
_playbackFile - > saveScreenShot ( screen , md5 ) ;
screen . free ( ) ;
}
}
}
bool EventRecorder : : grabScreenAndComputeMD5 ( Graphics : : Surface & screen , uint8 md5 [ 16 ] ) {
if ( ! createScreenShot ( screen ) ) {
warning ( " Can't save screenshot " ) ;
return false ;
}
2013-08-03 00:36:28 +00:00
Common : : MemoryReadStream bitmapStream ( ( const byte * ) screen . getPixels ( ) , screen . w * screen . h * screen . format . bytesPerPixel ) ;
2013-05-16 21:18:09 +00:00
computeStreamMD5 ( bitmapStream , md5 ) ;
return true ;
}
Common : : SeekableReadStream * EventRecorder : : processSaveStream ( const Common : : String & fileName ) {
Common : : InSaveFile * saveFile ;
switch ( _recordMode ) {
case kRecorderPlayback :
debugC ( 1 , kDebugLevelEventRec , " playback:action= \" Process save file \" filename=%s len=%d " , fileName . c_str ( ) , _playbackFile - > getHeader ( ) . saveFiles [ fileName ] . size ) ;
return new Common : : MemoryReadStream ( _playbackFile - > getHeader ( ) . saveFiles [ fileName ] . buffer , _playbackFile - > getHeader ( ) . saveFiles [ fileName ] . size ) ;
case kRecorderRecord :
saveFile = _realSaveManager - > openForLoading ( fileName ) ;
if ( saveFile ! = NULL ) {
_playbackFile - > addSaveFile ( fileName , saveFile ) ;
saveFile - > seek ( 0 ) ;
}
return saveFile ;
default :
return NULL ;
break ;
}
}
Common : : SaveFileManager * EventRecorder : : getSaveManager ( Common : : SaveFileManager * realSaveManager ) {
_realSaveManager = realSaveManager ;
if ( _recordMode ! = kPassthrough ) {
return & _fakeSaveManager ;
} else {
return realSaveManager ;
}
}
void EventRecorder : : preDrawOverlayGui ( ) {
if ( ( _initialized ) | | ( _needRedraw ) ) {
RecordMode oldMode = _recordMode ;
_recordMode = kPassthrough ;
g_system - > showOverlay ( ) ;
g_gui . theme ( ) - > clearAll ( ) ;
g_gui . theme ( ) - > openDialog ( true , GUI : : ThemeEngine : : kShadingNone ) ;
2013-07-14 16:16:01 +00:00
_controlPanel - > drawDialog ( ) ;
2013-05-16 21:18:09 +00:00
g_gui . theme ( ) - > finishBuffering ( ) ;
g_gui . theme ( ) - > updateScreen ( ) ;
_recordMode = oldMode ;
}
}
void EventRecorder : : postDrawOverlayGui ( ) {
if ( ( _initialized ) | | ( _needRedraw ) ) {
RecordMode oldMode = _recordMode ;
_recordMode = kPassthrough ;
g_system - > hideOverlay ( ) ;
_recordMode = oldMode ;
}
}
Common : : StringArray EventRecorder : : listSaveFiles ( const Common : : String & pattern ) {
if ( _recordMode = = kRecorderPlayback ) {
Common : : StringArray result ;
for ( Common : : HashMap < Common : : String , Common : : PlaybackFile : : SaveFileBuffer > : : iterator i = _playbackFile - > getHeader ( ) . saveFiles . begin ( ) ; i ! = _playbackFile - > getHeader ( ) . saveFiles . end ( ) ; + + i ) {
if ( i - > _key . matchString ( pattern , false , true ) ) {
result . push_back ( i - > _key ) ;
}
}
return result ;
} else {
return _realSaveManager - > listSavefiles ( pattern ) ;
}
}
void EventRecorder : : setFileHeader ( ) {
if ( _recordMode ! = kRecorderRecord ) {
return ;
}
TimeDate t ;
const EnginePlugin * plugin = 0 ;
GameDescriptor desc = EngineMan . findGame ( ConfMan . getActiveDomainName ( ) , & plugin ) ;
g_system - > getTimeAndDate ( t ) ;
if ( _author . empty ( ) ) {
setAuthor ( " Unknown Author " ) ;
}
if ( _name . empty ( ) ) {
g_eventRec . setName ( Common : : String : : format ( " %.2d.%.2d.%.4d " , t . tm_mday , t . tm_mon , 1900 + t . tm_year ) + desc . description ( ) ) ;
}
_playbackFile - > getHeader ( ) . author = _author ;
_playbackFile - > getHeader ( ) . notes = _desc ;
_playbackFile - > getHeader ( ) . name = _name ;
}
SDL_Surface * EventRecorder : : getSurface ( int width , int height ) {
2013-07-04 13:41:01 +00:00
// Create a RGB565 surface of the requested dimensions.
return SDL_CreateRGBSurface ( SDL_SWSURFACE , width , height , 16 , 0xF800 , 0x07E0 , 0x001F , 0x0000 ) ;
2013-05-16 21:18:09 +00:00
}
bool EventRecorder : : switchMode ( ) {
const Common : : String gameId = ConfMan . get ( " gameid " ) ;
const EnginePlugin * plugin = 0 ;
EngineMan . findGame ( gameId , & plugin ) ;
bool metaInfoSupport = ( * plugin ) - > hasFeature ( MetaEngine : : kSavesSupportMetaInfo ) ;
bool featuresSupport = metaInfoSupport & &
g_engine - > canSaveGameStateCurrently ( ) & &
( * plugin ) - > hasFeature ( MetaEngine : : kSupportsListSaves ) & &
( * plugin ) - > hasFeature ( MetaEngine : : kSupportsDeleteSave ) ;
if ( ! featuresSupport ) {
return false ;
}
int emptySlot = 1 ;
SaveStateList saveList = ( * plugin ) - > listSaves ( gameId . c_str ( ) ) ;
for ( SaveStateList : : const_iterator x = saveList . begin ( ) ; x ! = saveList . end ( ) ; + + x ) {
int saveSlot = x - > getSaveSlot ( ) ;
if ( saveSlot = = 0 ) {
continue ;
}
if ( emptySlot ! = saveSlot ) {
break ;
}
emptySlot + + ;
}
Common : : String saveName ;
if ( emptySlot > = 0 ) {
saveName = Common : : String : : format ( " Save %d " , emptySlot + 1 ) ;
Common : : Error status = g_engine - > saveGameState ( emptySlot , saveName ) ;
if ( status . getCode ( ) = = Common : : kNoError ) {
Common : : Event eventRTL ;
eventRTL . type = Common : : EVENT_RTL ;
g_system - > getEventManager ( ) - > pushEvent ( eventRTL ) ;
}
}
ConfMan . set ( " record_mode " , " " , Common : : ConfigManager : : kTransientDomain ) ;
ConfMan . setInt ( " save_slot " , emptySlot , Common : : ConfigManager : : kTransientDomain ) ;
_needcontinueGame = true ;
return true ;
}
bool EventRecorder : : checkForContinueGame ( ) {
bool result = _needcontinueGame ;
_needcontinueGame = false ;
return result ;
}
void EventRecorder : : deleteTemporarySave ( ) {
if ( _temporarySlot = = - 1 ) return ;
const Common : : String gameId = ConfMan . get ( " gameid " ) ;
const EnginePlugin * plugin = 0 ;
EngineMan . findGame ( gameId , & plugin ) ;
( * plugin ) - > removeSaveState ( gameId . c_str ( ) , _temporarySlot ) ;
_temporarySlot = - 1 ;
}
} // End of namespace GUI
# endif // ENABLE_EVENTRECORDER