00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define FORBIDDEN_SYMBOL_EXCEPTION_fprintf
00024 #define FORBIDDEN_SYMBOL_EXCEPTION_fgetc
00025 #define FORBIDDEN_SYMBOL_EXCEPTION_stderr
00026 #define FORBIDDEN_SYMBOL_EXCEPTION_stdin
00027
00028 #include "common/archive.h"
00029 #include "common/debug-channels.h"
00030 #include "common/file.h"
00031 #include "common/foreach.h"
00032 #include "common/fs.h"
00033 #include "common/config-manager.h"
00034 #include "common/translation.h"
00035
00036 #include "graphics/pixelbuffer.h"
00037 #include "graphics/renderer.h"
00038
00039 #ifdef USE_OPENGL
00040 #include "graphics/opengl/context.h"
00041 #endif
00042
00043 #include "gui/error.h"
00044 #include "gui/gui-manager.h"
00045 #include "gui/message.h"
00046
00047 #include "image/png.h"
00048
00049 #include "engines/engine.h"
00050
00051 #include "engines/grim/md5check.h"
00052 #include "engines/grim/md5checkdialog.h"
00053 #include "engines/grim/debug.h"
00054 #include "engines/grim/grim.h"
00055 #include "engines/grim/lua.h"
00056 #include "engines/grim/lua_v1.h"
00057 #include "engines/grim/emi/poolsound.h"
00058 #include "engines/grim/emi/layer.h"
00059 #include "engines/grim/actor.h"
00060 #include "engines/grim/movie/movie.h"
00061 #include "engines/grim/savegame.h"
00062 #include "engines/grim/registry.h"
00063 #include "engines/grim/resource.h"
00064 #include "engines/grim/localize.h"
00065 #include "engines/grim/gfx_base.h"
00066 #include "engines/grim/bitmap.h"
00067 #include "engines/grim/font.h"
00068 #include "engines/grim/primitives.h"
00069 #include "engines/grim/objectstate.h"
00070 #include "engines/grim/set.h"
00071 #include "engines/grim/sound.h"
00072 #include "engines/grim/stuffit.h"
00073 #include "engines/grim/debugger.h"
00074
00075 #include "engines/grim/imuse/imuse.h"
00076 #include "engines/grim/emi/sound/emisound.h"
00077
00078 #include "engines/grim/lua/lua.h"
00079
00080 namespace Grim {
00081
00082 GrimEngine *g_grim = nullptr;
00083 GfxBase *g_driver = nullptr;
00084 int g_imuseState = -1;
00085
00086 GrimEngine::GrimEngine(OSystem *syst, uint32 gameFlags, GrimGameType gameType, Common::Platform platform, Common::Language language) :
00087 Engine(syst), _currSet(nullptr), _selectedActor(nullptr), _pauseStartTime(0) {
00088 g_grim = this;
00089
00090 _debugger = new Debugger();
00091 _gameType = gameType;
00092 _gameFlags = gameFlags;
00093 _gamePlatform = platform;
00094 _gameLanguage = language;
00095
00096 if (getGameType() == GType_GRIM)
00097 g_registry = new Registry();
00098 else
00099 g_registry = nullptr;
00100
00101 g_resourceloader = nullptr;
00102 g_localizer = nullptr;
00103 g_movie = nullptr;
00104 g_imuse = nullptr;
00105
00106
00107 ConfMan.registerDefault("use_arb_shaders", true);
00108
00109 _showFps = ConfMan.getBool("show_fps");
00110
00111 _softRenderer = true;
00112
00113 _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, 192);
00114 _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
00115 _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
00116 _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
00117
00118 _currSet = nullptr;
00119 _selectedActor = nullptr;
00120 _controlsEnabled = new bool[KEYCODE_EXTRA_LAST];
00121 _controlsState = new bool[KEYCODE_EXTRA_LAST];
00122 for (int i = 0; i < KEYCODE_EXTRA_LAST; i++) {
00123 _controlsEnabled[i] = false;
00124 _controlsState[i] = false;
00125 }
00126 _joyAxisPosition = new float[NUM_JOY_AXES];
00127 for (int i = 0; i < NUM_JOY_AXES; i++) {
00128 _joyAxisPosition[i] = 0;
00129 }
00130 _speechMode = TextAndVoice;
00131 _textSpeed = 7;
00132 _mode = _previousMode = NormalMode;
00133 _flipEnable = true;
00134 int speed = ConfMan.getInt("engine_speed");
00135 if (speed == 0) {
00136 _speedLimitMs = 0;
00137 } else if (speed < 0 || speed > 100) {
00138 _speedLimitMs = 1000 / 60;
00139 ConfMan.setInt("engine_speed", 1000 / _speedLimitMs);
00140 } else {
00141 _speedLimitMs = 1000 / speed;
00142 }
00143 _listFilesIter = nullptr;
00144 _savedState = nullptr;
00145 _fps[0] = 0;
00146 _iris = new Iris();
00147 _buildActiveActorsList = false;
00148
00149 Color c(0, 0, 0);
00150
00151 _printLineDefaults.setX(0);
00152 _printLineDefaults.setY(100);
00153 _printLineDefaults.setWidth(0);
00154 _printLineDefaults.setHeight(0);
00155 _printLineDefaults.setFGColor(c);
00156 _printLineDefaults.setFont(nullptr);
00157 _printLineDefaults.setJustify(TextObject::LJUSTIFY);
00158
00159 _sayLineDefaults.setX(0);
00160 _sayLineDefaults.setY(100);
00161 _sayLineDefaults.setWidth(0);
00162 _sayLineDefaults.setHeight(0);
00163 _sayLineDefaults.setFGColor(c);
00164 _sayLineDefaults.setFont(nullptr);
00165 _sayLineDefaults.setJustify(TextObject::CENTER);
00166
00167 _blastTextDefaults.setX(0);
00168 _blastTextDefaults.setY(200);
00169 _blastTextDefaults.setWidth(0);
00170 _blastTextDefaults.setHeight(0);
00171 _blastTextDefaults.setFGColor(c);
00172 _blastTextDefaults.setFont(nullptr);
00173 _blastTextDefaults.setJustify(TextObject::LJUSTIFY);
00174
00175 const Common::FSNode gameDataDir(ConfMan.get("path"));
00176 SearchMan.addSubDirectoryMatching(gameDataDir, "movies");
00177 SearchMan.addSubDirectoryMatching(gameDataDir, "credits");
00178 SearchMan.addSubDirectoryMatching(gameDataDir, "widescreen");
00179
00180 Debug::registerDebugChannels();
00181 }
00182
00183 GrimEngine::~GrimEngine() {
00184 delete[] _controlsEnabled;
00185 delete[] _controlsState;
00186 delete[] _joyAxisPosition;
00187
00188 clearPools();
00189
00190 delete LuaBase::instance();
00191 if (g_registry) {
00192 g_registry->save();
00193 delete g_registry;
00194 g_registry = nullptr;
00195 }
00196 delete g_movie;
00197 g_movie = nullptr;
00198 delete g_imuse;
00199 g_imuse = nullptr;
00200 delete g_emiSound;
00201 g_emiSound = nullptr;
00202 delete g_sound;
00203 g_sound = nullptr;
00204 delete g_localizer;
00205 g_localizer = nullptr;
00206 delete g_resourceloader;
00207 g_resourceloader = nullptr;
00208 delete g_driver;
00209 g_driver = nullptr;
00210 delete _iris;
00211 delete _debugger;
00212
00213 ConfMan.flushToDisk();
00214 DebugMan.clearAllDebugChannels();
00215
00216 g_grim = nullptr;
00217 }
00218
00219 void GrimEngine::clearPools() {
00220 Set::getPool().deleteObjects();
00221 Actor::getPool().deleteObjects();
00222 PrimitiveObject::getPool().deleteObjects();
00223 TextObject::getPool().deleteObjects();
00224 Bitmap::getPool().deleteObjects();
00225 Font::getPool().deleteObjects();
00226 ObjectState::getPool().deleteObjects();
00227
00228 _currSet = nullptr;
00229 }
00230
00231 LuaBase *GrimEngine::createLua() {
00232 return new Lua_V1();
00233 }
00234
00235 GfxBase *GrimEngine::createRenderer(int screenW, int screenH, bool fullscreen) {
00236 Common::String rendererConfig = ConfMan.get("renderer");
00237 Graphics::RendererType desiredRendererType = Graphics::parseRendererTypeCode(rendererConfig);
00238 Graphics::RendererType matchingRendererType = Graphics::getBestMatchingAvailableRendererType(desiredRendererType);
00239
00240 _softRenderer = matchingRendererType == Graphics::kRendererTypeTinyGL;
00241 _system->setupScreen(screenW, screenH, fullscreen, !_softRenderer);
00242
00243 #if defined(USE_OPENGL)
00244
00245 if (matchingRendererType == Graphics::kRendererTypeOpenGLShaders && !OpenGLContext.shadersSupported) {
00246 matchingRendererType = Graphics::kRendererTypeOpenGL;
00247 }
00248 #endif
00249
00250 if (matchingRendererType != desiredRendererType && desiredRendererType != Graphics::kRendererTypeDefault) {
00251
00252 warning("Unable to create a '%s' renderer", rendererConfig.c_str());
00253 }
00254
00255 GfxBase *renderer = nullptr;
00256 #if defined(USE_GLES2) || defined(USE_OPENGL_SHADERS)
00257 if (matchingRendererType == Graphics::kRendererTypeOpenGLShaders) {
00258 renderer = CreateGfxOpenGLShader();
00259 }
00260 #endif
00261 #if defined(USE_OPENGL) && !defined(USE_GLES2)
00262 if (matchingRendererType == Graphics::kRendererTypeOpenGL) {
00263 renderer = CreateGfxOpenGL();
00264 }
00265 #endif
00266 if (matchingRendererType == Graphics::kRendererTypeTinyGL) {
00267 renderer = CreateGfxTinyGL();
00268 }
00269
00270 if (!renderer) {
00271 error("Unable to create a '%s' renderer", rendererConfig.c_str());
00272 }
00273
00274 renderer->setupScreen(screenW, screenH, fullscreen);
00275 renderer->loadEmergFont();
00276 return renderer;
00277 }
00278
00279 const char *GrimEngine::getUpdateFilename() {
00280 if (!(getGameFlags() & ADGF_DEMO))
00281 return "gfupd101.exe";
00282 else
00283 return nullptr;
00284 }
00285
00286 Common::Error GrimEngine::run() {
00287
00288
00289 if (getGameType() == GType_MONKEY4) {
00290 if (SearchMan.hasFile("Monkey Island 4 Installer")) {
00291 StuffItArchive *archive = new StuffItArchive();
00292
00293 if (archive->open("Monkey Island 4 Installer"))
00294 SearchMan.add("Monkey Island 4 Installer", archive, 0, true);
00295 else
00296 delete archive;
00297 }
00298 if (SearchMan.hasFile("EFMI Installer")) {
00299 StuffItArchive *archive = new StuffItArchive();
00300
00301 if (archive->open("EFMI Installer"))
00302 SearchMan.add("EFMI Installer", archive, 0, true);
00303 else
00304 delete archive;
00305
00306 }
00307 }
00308
00309 ConfMan.registerDefault("check_gamedata", true);
00310 if (ConfMan.getBool("check_gamedata")) {
00311 MD5CheckDialog d;
00312 if (!d.runModal()) {
00313 Common::String confirmString = Common::String::format(_(
00314 "ResidualVM found some problems with your game data files.\n"
00315 "Running ResidualVM nevertheless may cause game bugs or even crashes.\n"
00316 "Do you still want to run %s?"),
00317 GType_MONKEY4 == getGameType() ? _("Escape From Monkey Island") : _("Grim Fandango")
00318 );
00319 GUI::MessageDialog msg(confirmString, _("Yes"), _("No"));
00320 if (!msg.runModal()) {
00321 return Common::kUserCanceled;
00322 }
00323 }
00324
00325 ConfMan.setBool("check_gamedata", false);
00326 ConfMan.flushToDisk();
00327 }
00328
00329 g_resourceloader = new ResourceLoader();
00330 bool demo = getGameFlags() & ADGF_DEMO;
00331 if (getGameType() == GType_GRIM)
00332 g_movie = CreateSmushPlayer(demo);
00333 else if (getGameType() == GType_MONKEY4) {
00334 if (_gamePlatform == Common::kPlatformPS2)
00335 g_movie = CreateMpegPlayer();
00336 else
00337 g_movie = CreateBinkPlayer(demo);
00338 }
00339 if (getGameType() == GType_GRIM) {
00340 g_imuse = new Imuse(20, demo);
00341 g_emiSound = nullptr;
00342 } else if (getGameType() == GType_MONKEY4) {
00343 g_emiSound = new EMISound(20);
00344 g_imuse = nullptr;
00345 }
00346 g_sound = new SoundPlayer();
00347
00348 bool fullscreen = ConfMan.getBool("fullscreen");
00349 g_driver = createRenderer(640, 480, fullscreen);
00350
00351 if (getGameType() == GType_MONKEY4 && SearchMan.hasFile("AMWI.m4b")) {
00352
00353 playAspyrLogo();
00354 }
00355
00356 Bitmap *splash_bm = nullptr;
00357 if (!(_gameFlags & ADGF_DEMO) && getGameType() == GType_GRIM)
00358 splash_bm = Bitmap::create("splash.bm");
00359 else if ((_gameFlags & ADGF_DEMO) && getGameType() == GType_MONKEY4)
00360 splash_bm = Bitmap::create("splash.til");
00361 else if (getGamePlatform() == Common::kPlatformPS2 && getGameType() == GType_MONKEY4)
00362 splash_bm = Bitmap::create("load.tga");
00363
00364 g_driver->clearScreen();
00365
00366 if (splash_bm != nullptr)
00367 splash_bm->draw();
00368
00369
00370
00371 if (_softRenderer)
00372 g_driver->flipBuffer();
00373
00374 LuaBase *lua = createLua();
00375
00376 lua->registerOpcodes();
00377 lua->registerLua();
00378
00379
00380 if (getGameType() == GType_GRIM && _gameFlags & ADGF_DEMO) {
00381 lua->forceDemo();
00382 }
00383
00384
00385 g_localizer = new Localizer();
00386 lua->loadSystemScript();
00387 lua->boot();
00388
00389 _savegameLoadRequest = false;
00390 _savegameSaveRequest = false;
00391
00392
00393 if (ConfMan.hasKey("save_slot")) {
00394 loadGameState(ConfMan.getInt("save_slot"));
00395 }
00396
00397 g_grim->setMode(NormalMode);
00398 delete splash_bm;
00399 g_grim->mainLoop();
00400
00401 return Common::kNoError;
00402 }
00403
00404 void GrimEngine::playAspyrLogo() {
00405
00406
00407
00408
00409
00410
00411 MoviePlayer *defaultPlayer = g_movie;
00412 g_movie = CreateQuickTimePlayer();
00413 g_movie->play("AMWI.m4b", false, 0, 0);
00414 setMode(SmushMode);
00415 while (g_movie->isPlaying()) {
00416 _doFlip = true;
00417 uint32 startTime = g_system->getMillis();
00418
00419 updateDisplayScene();
00420 if (_doFlip) {
00421 doFlip();
00422 }
00423
00424 Common::Event event;
00425 while (g_system->getEventManager()->pollEvent(event)) {
00426
00427 Common::EventType type = event.type;
00428 if (type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) {
00429 g_movie->stop();
00430 break;
00431 }
00432 }
00433
00434 uint32 endTime = g_system->getMillis();
00435 if (startTime > endTime)
00436 continue;
00437 uint32 diffTime = endTime - startTime;
00438 if (_speedLimitMs == 0)
00439 continue;
00440 if (diffTime < _speedLimitMs) {
00441 uint32 delayTime = _speedLimitMs - diffTime;
00442 g_system->delayMillis(delayTime);
00443 }
00444 }
00445 delete g_movie;
00446 setMode(NormalMode);
00447 g_movie = defaultPlayer;
00448 }
00449
00450 Common::Error GrimEngine::loadGameState(int slot) {
00451 assert(slot >= 0);
00452 if (getGameType() == GType_MONKEY4) {
00453 if (getGamePlatform() == Common::kPlatformPS2) {
00454 _savegameFileName = Common::String::format("efmi%03d.ps2", slot);
00455 } else {
00456 _savegameFileName = Common::String::format("efmi%03d.gsv", slot);
00457 }
00458 } else {
00459 _savegameFileName = Common::String::format("grim%02d.gsv", slot);
00460 }
00461 _savegameLoadRequest = true;
00462 return Common::kNoError;
00463 }
00464
00465 void GrimEngine::handlePause() {
00466 if (!LuaBase::instance()->callback("pauseHandler")) {
00467 error("handlePause: invalid handler");
00468 }
00469 }
00470
00471 void GrimEngine::handleExit() {
00472 if (!LuaBase::instance()->callback("exitHandler")) {
00473 error("handleExit: invalid handler");
00474 }
00475 }
00476
00477 void GrimEngine::handleUserPaint() {
00478 if (!LuaBase::instance()->callback("userPaintHandler")) {
00479 error("handleUserPaint: invalid handler");
00480 }
00481 }
00482
00483 void GrimEngine::cameraChangeHandle(int prev, int next) {
00484 LuaObjects objects;
00485 objects.add(prev);
00486 objects.add(next);
00487 LuaBase::instance()->callback("camChangeHandler", objects);
00488 }
00489
00490 void GrimEngine::cameraPostChangeHandle(int num) {
00491 LuaObjects objects;
00492 objects.add(num);
00493 LuaBase::instance()->callback("postCamChangeHandler", objects);
00494 }
00495
00496 void GrimEngine::savegameCallback() {
00497 if (!LuaBase::instance()->callback("saveGameCallback")) {
00498 error("GrimEngine::savegameCallback: invalid handler");
00499 }
00500 }
00501
00502 void GrimEngine::handleDebugLoadResource() {
00503 void *resource = nullptr;
00504 int c, i = 0;
00505 char buf[513];
00506
00507
00508
00509 fprintf(stderr, "Enter resource to load (extension specifies type): ");
00510 while (i < 512 && (c = fgetc(stdin)) != EOF && c != '\n')
00511 buf[i++] = c;
00512
00513 buf[i] = '\0';
00514 if (strstr(buf, ".key"))
00515 resource = (void *)g_resourceloader->loadKeyframe(buf);
00516 else if (strstr(buf, ".zbm") || strstr(buf, ".bm"))
00517 resource = (void *)Bitmap::create(buf);
00518 else if (strstr(buf, ".cmp"))
00519 resource = (void *)g_resourceloader->loadColormap(buf);
00520 else if (strstr(buf, ".cos"))
00521 resource = (void *)g_resourceloader->loadCostume(buf, nullptr, nullptr);
00522 else if (strstr(buf, ".lip"))
00523 resource = (void *)g_resourceloader->loadLipSync(buf);
00524 else if (strstr(buf, ".snm"))
00525 resource = (void *)g_movie->play(buf, false, 0, 0);
00526 else if (strstr(buf, ".wav") || strstr(buf, ".imu")) {
00527 if (g_imuse)
00528 g_imuse->startSfx(buf);
00529 resource = (void *)1;
00530 } else if (strstr(buf, ".mat")) {
00531 CMap *cmap = g_resourceloader->loadColormap("item.cmp");
00532 warning("Default colormap applied to resources loaded in this fashion");
00533
00534 resource = (void *)g_resourceloader->loadMaterial(buf, cmap, false);
00535 } else {
00536 warning("Resource type not understood");
00537 }
00538 if (!resource)
00539 warning("Requested resouce (%s) not found", buf);
00540 }
00541
00542 void GrimEngine::drawTextObjects() {
00543 foreach (TextObject *t, TextObject::getPool()) {
00544 t->draw();
00545 }
00546 }
00547
00548 void GrimEngine::playIrisAnimation(Iris::Direction dir, int x, int y, int time) {
00549 _iris->play(dir, x, y, time);
00550 }
00551
00552 void GrimEngine::luaUpdate() {
00553 if (_savegameLoadRequest || _savegameSaveRequest || _changeHardwareState)
00554 return;
00555
00556
00557 unsigned newStart = g_system->getMillis();
00558 if (newStart < _frameStart) {
00559 _frameStart = newStart;
00560 return;
00561 }
00562 _frameTime = newStart - _frameStart;
00563 _frameStart = newStart;
00564
00565 if (_mode == PauseMode || _shortFrame) {
00566 _frameTime = 0;
00567 }
00568
00569 LuaBase::instance()->update(_frameTime, _movieTime);
00570
00571 if (_currSet && (_mode == NormalMode || _mode == SmushMode)) {
00572
00573
00574 for (Common::List<Actor *>::iterator i = _talkingActors.begin(); i != _talkingActors.end(); ++i) {
00575 Actor *a = *i;
00576 if (!a->updateTalk(_frameTime)) {
00577 i = _talkingActors.reverse_erase(i);
00578 }
00579 }
00580
00581
00582
00583 buildActiveActorsList();
00584 foreach (Actor *a, _activeActors) {
00585
00586
00587
00588 a->update(_frameTime);
00589 }
00590
00591 _iris->update(_frameTime);
00592
00593 foreach (TextObject *t, TextObject::getPool()) {
00594 t->update();
00595 }
00596 }
00597 }
00598
00599 void GrimEngine::updateDisplayScene() {
00600 _doFlip = true;
00601
00602 if (_mode == SmushMode) {
00603 if (g_movie->isPlaying()) {
00604 _movieTime = g_movie->getMovieTime();
00605 if (g_movie->isUpdateNeeded()) {
00606 g_driver->prepareMovieFrame(g_movie->getDstSurface());
00607 g_movie->clearUpdateNeeded();
00608 }
00609 int frame = g_movie->getFrame();
00610 if (frame >= 0) {
00611 if (frame != _prevSmushFrame) {
00612 _prevSmushFrame = g_movie->getFrame();
00613 g_driver->drawMovieFrame(g_movie->getX(), g_movie->getY());
00614 if (_showFps)
00615 g_driver->drawEmergString(550, 25, _fps, Color(255, 255, 255));
00616 } else
00617 _doFlip = false;
00618 } else
00619 g_driver->releaseMovieFrame();
00620 }
00621
00622 _iris->draw();
00623 if (_movieSubtitle) {
00624 _movieSubtitle->draw();
00625 }
00626 } else if (_mode == NormalMode || _mode == OverworldMode) {
00627 updateNormalMode();
00628 } else if (_mode == DrawMode) {
00629 updateDrawMode();
00630 }
00631 }
00632
00633 void GrimEngine::updateNormalMode() {
00634 if (!_currSet || !_flipEnable)
00635 return;
00636
00637 g_driver->clearScreen();
00638
00639 drawNormalMode();
00640
00641 _iris->draw();
00642 drawTextObjects();
00643 }
00644
00645 void GrimEngine::updateDrawMode() {
00646 _doFlip = false;
00647 _prevSmushFrame = 0;
00648 _movieTime = 0;
00649 }
00650
00651 void GrimEngine::drawNormalMode() {
00652 _prevSmushFrame = 0;
00653 _movieTime = 0;
00654
00655 _currSet->drawBackground();
00656
00657
00658
00659
00660 _currSet->drawBitmaps(ObjectState::OBJSTATE_BACKGROUND);
00661
00662
00663
00664 _currSet->drawBitmaps(ObjectState::OBJSTATE_STATE);
00665
00666
00667
00668
00669
00670
00671
00672 if (g_movie->isPlaying() && _movieSetup == _currSet->getCurrSetup()->_name) {
00673 _movieTime = g_movie->getMovieTime();
00674 if (g_movie->isUpdateNeeded()) {
00675 g_driver->prepareMovieFrame(g_movie->getDstSurface());
00676 g_movie->clearUpdateNeeded();
00677 }
00678 if (g_movie->getFrame() >= 0)
00679 g_driver->drawMovieFrame(g_movie->getX(), g_movie->getY());
00680 else
00681 g_driver->releaseMovieFrame();
00682 }
00683
00684
00685
00686
00687 _currSet->drawBitmaps(ObjectState::OBJSTATE_UNDERLAY);
00688
00689
00690 foreach (PrimitiveObject *p, PrimitiveObject::getPool()) {
00691 p->draw();
00692 }
00693
00694 _currSet->setupCamera();
00695
00696 g_driver->set3DMode();
00697
00698 if (_setupChanged) {
00699 cameraPostChangeHandle(_currSet->getSetup());
00700 _setupChanged = false;
00701 setSideTextures(_currSet->getCurrSetup()->_name.c_str());
00702 }
00703
00704
00705 buildActiveActorsList();
00706 foreach (Actor *a, _activeActors) {
00707 if (a->isVisible())
00708 a->draw();
00709 }
00710
00711 flagRefreshShadowMask(false);
00712
00713
00714
00715
00716 _currSet->drawBitmaps(ObjectState::OBJSTATE_OVERLAY);
00717 }
00718
00719 void GrimEngine::doFlip() {
00720 _frameCounter++;
00721 if (!_doFlip) {
00722 return;
00723 }
00724
00725 if (_showFps && _mode != DrawMode)
00726 g_driver->drawEmergString(550, 25, _fps, Color(255, 255, 255));
00727
00728 if (_flipEnable)
00729 g_driver->flipBuffer();
00730
00731 if (_showFps && _mode != DrawMode) {
00732 unsigned int currentTime = g_system->getMillis();
00733 unsigned int delta = currentTime - _lastFrameTime;
00734 if (delta > 500) {
00735 snprintf(_fps, sizeof(_fps), "%7.2f", (double)(_frameCounter * 1000) / (double)delta);
00736 _frameCounter = 0;
00737 _lastFrameTime = currentTime;
00738 }
00739 }
00740 }
00741
00742 void GrimEngine::mainLoop() {
00743 _movieTime = 0;
00744 _frameTime = 0;
00745 _frameStart = g_system->getMillis();
00746 _frameCounter = 0;
00747 _lastFrameTime = 0;
00748 _prevSmushFrame = 0;
00749 _refreshShadowMask = false;
00750 _shortFrame = false;
00751 bool resetShortFrame = false;
00752 _changeHardwareState = false;
00753 _changeFullscreenState = false;
00754 _setupChanged = true;
00755
00756 for (;;) {
00757 uint32 startTime = g_system->getMillis();
00758 if (_shortFrame) {
00759 if (resetShortFrame) {
00760 _shortFrame = false;
00761 }
00762 resetShortFrame = !resetShortFrame;
00763 }
00764
00765 if (shouldQuit())
00766 return;
00767
00768 if (_savegameLoadRequest) {
00769 savegameRestore();
00770 }
00771 if (_savegameSaveRequest) {
00772 savegameSave();
00773 }
00774
00775
00776
00777 if (_changeFullscreenState &&
00778 _system->hasFeature(OSystem::kFeatureFullscreenToggleKeepsContext)) {
00779 bool fullscreen = _system->getFeatureState(OSystem::kFeatureFullscreenMode);
00780 _system->setFeatureState(OSystem::kFeatureFullscreenMode, !fullscreen);
00781 _changeFullscreenState = false;
00782 }
00783
00784
00785
00786 if (_changeHardwareState || _changeFullscreenState) {
00787 _changeHardwareState = false;
00788
00789 bool fullscreen = _system->getFeatureState(OSystem::kFeatureFullscreenMode);
00790 if (_changeFullscreenState) {
00791 fullscreen = !fullscreen;
00792 }
00793
00794 uint screenWidth = g_driver->getScreenWidth();
00795 uint screenHeight = g_driver->getScreenHeight();
00796
00797 EngineMode mode = getMode();
00798
00799 _savegameFileName = "";
00800 savegameSave();
00801 clearPools();
00802
00803 delete g_driver;
00804 g_driver = createRenderer(screenWidth, screenHeight, fullscreen);
00805 savegameRestore();
00806
00807 if (mode == DrawMode) {
00808 setMode(GrimEngine::NormalMode);
00809 updateDisplayScene();
00810 g_driver->storeDisplay();
00811 g_driver->dimScreen();
00812 }
00813 setMode(mode);
00814 _changeFullscreenState = false;
00815 }
00816
00817 g_sound->flushTracks();
00818 if (g_imuse) {
00819 g_imuse->refreshScripts();
00820 }
00821
00822 _debugger->onFrame();
00823
00824
00825 Common::Event event;
00826 while (g_system->getEventManager()->pollEvent(event)) {
00827
00828 Common::EventType type = event.type;
00829 if (type == Common::EVENT_KEYDOWN || type == Common::EVENT_KEYUP) {
00830 if (type == Common::EVENT_KEYDOWN) {
00831
00832
00833
00834 if (_mode == SmushMode && g_grim->getGameType() == GType_MONKEY4) {
00835 if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
00836 g_movie->stop();
00837 break;
00838 }
00839 continue;
00840 }
00841
00842 if (_mode != DrawMode && _mode != SmushMode && (event.kbd.ascii == 'q')) {
00843 handleExit();
00844 break;
00845 } else if (_mode != DrawMode && (event.kbd.keycode == Common::KEYCODE_PAUSE)) {
00846 handlePause();
00847 break;
00848 } else {
00849 handleChars(type, event.kbd);
00850 }
00851 }
00852
00853 handleControls(type, event.kbd);
00854
00855 if (getGameType() != GType_MONKEY4) {
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 if (!(getGamePlatform() == Common::kPlatformPS2 && _mode == SmushMode)) {
00869 luaUpdate();
00870 }
00871 }
00872 }
00873 if (type == Common::EVENT_JOYAXIS_MOTION)
00874 handleJoyAxis(event.joystick.axis, event.joystick.position);
00875 if (type == Common::EVENT_JOYBUTTON_DOWN || type == Common::EVENT_JOYBUTTON_UP)
00876 handleJoyButton(type, event.joystick.button);
00877 if (type == Common::EVENT_SCREEN_CHANGED) {
00878 handleUserPaint();
00879 }
00880 }
00881
00882 if (_mode != PauseMode) {
00883
00884
00885
00886
00887
00888
00889 updateDisplayScene();
00890 }
00891
00892 if (_mode != PauseMode) {
00893 doFlip();
00894 }
00895
00896
00897 if (!(getGamePlatform() == Common::kPlatformPS2 && _mode == SmushMode)) {
00898 luaUpdate();
00899 }
00900
00901 if (g_imuseState != -1) {
00902 g_sound->setMusicState(g_imuseState);
00903 g_imuseState = -1;
00904 }
00905
00906 uint32 endTime = g_system->getMillis();
00907 if (startTime > endTime)
00908 continue;
00909 uint32 diffTime = endTime - startTime;
00910 if (_speedLimitMs == 0)
00911 continue;
00912 if (diffTime < _speedLimitMs) {
00913 uint32 delayTime = _speedLimitMs - diffTime;
00914 g_system->delayMillis(delayTime);
00915 }
00916 }
00917 }
00918
00919 void GrimEngine::changeHardwareState() {
00920 _changeHardwareState = true;
00921 }
00922
00923 void GrimEngine::saveGame(const Common::String &file) {
00924 _savegameFileName = file;
00925 _savegameSaveRequest = true;
00926 }
00927
00928 void GrimEngine::loadGame(const Common::String &file) {
00929 _savegameFileName = file;
00930 _savegameLoadRequest = true;
00931 }
00932
00933 void GrimEngine::savegameRestore() {
00934 debug("GrimEngine::savegameRestore() started.");
00935 _savegameLoadRequest = false;
00936 Common::String filename;
00937 if (_savegameFileName.size() == 0) {
00938 filename = "grim.sav";
00939 } else {
00940 filename = _savegameFileName;
00941 }
00942 _savedState = SaveGame::openForLoading(filename);
00943 if (!_savedState || !_savedState->isCompatible())
00944 return;
00945 if (g_imuse) {
00946 g_imuse->stopAllSounds();
00947 g_imuse->resetState();
00948 }
00949 g_movie->stop();
00950 if (g_imuse)
00951 g_imuse->pause(true);
00952 g_movie->pause(true);
00953 if (g_registry)
00954 g_registry->save();
00955
00956 _selectedActor = nullptr;
00957 delete _currSet;
00958 _currSet = nullptr;
00959
00960 Bitmap::getPool().restoreObjects(_savedState);
00961 Debug::debug(Debug::Engine, "Bitmaps restored successfully.");
00962
00963 Font::getPool().restoreObjects(_savedState);
00964 Debug::debug(Debug::Engine, "Fonts restored successfully.");
00965
00966 ObjectState::getPool().restoreObjects(_savedState);
00967 Debug::debug(Debug::Engine, "ObjectStates restored successfully.");
00968
00969 Set::getPool().restoreObjects(_savedState);
00970 Debug::debug(Debug::Engine, "Sets restored successfully.");
00971
00972 TextObject::getPool().restoreObjects(_savedState);
00973 Debug::debug(Debug::Engine, "TextObjects restored successfully.");
00974
00975 PrimitiveObject::getPool().restoreObjects(_savedState);
00976 Debug::debug(Debug::Engine, "PrimitiveObjects restored successfully.");
00977
00978 Actor::getPool().restoreObjects(_savedState);
00979 Debug::debug(Debug::Engine, "Actors restored successfully.");
00980
00981 if (getGameType() == GType_MONKEY4) {
00982 PoolSound::getPool().restoreObjects(_savedState);
00983 Debug::debug(Debug::Engine, "Pool sounds saved successfully.");
00984
00985 Layer::getPool().restoreObjects(_savedState);
00986 Debug::debug(Debug::Engine, "Layers restored successfully.");
00987 }
00988
00989 restoreGRIM();
00990 Debug::debug(Debug::Engine, "Engine restored successfully.");
00991
00992 g_driver->restoreState(_savedState);
00993 Debug::debug(Debug::Engine, "Renderer restored successfully.");
00994
00995 g_sound->restoreState(_savedState);
00996 Debug::debug(Debug::Engine, "iMuse restored successfully.");
00997
00998 g_movie->restoreState(_savedState);
00999 Debug::debug(Debug::Engine, "Movie restored successfully.");
01000
01001 _iris->restoreState(_savedState);
01002 Debug::debug(Debug::Engine, "Iris restored successfully.");
01003
01004 lua_Restore(_savedState);
01005 Debug::debug(Debug::Engine, "Lua restored successfully.");
01006
01007 delete _savedState;
01008
01009
01010
01011 _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
01012 _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
01013 _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
01014
01015 LuaBase::instance()->postRestoreHandle();
01016 if (g_imuse)
01017 g_imuse->pause(false);
01018 g_movie->pause(false);
01019 debug("GrimEngine::savegameRestore() finished.");
01020
01021 _shortFrame = true;
01022 clearEventQueue();
01023 invalidateActiveActorsList();
01024 buildActiveActorsList();
01025
01026 _currSet->setupCamera();
01027 g_driver->set3DMode();
01028 }
01029
01030 void GrimEngine::restoreGRIM() {
01031 _savedState->beginSection('GRIM');
01032
01033 _mode = (EngineMode)_savedState->readLEUint32();
01034 _previousMode = (EngineMode)_savedState->readLEUint32();
01035
01036
01037 int32 id = _savedState->readLESint32();
01038 if (id != 0) {
01039 _selectedActor = Actor::getPool().getObject(id);
01040 }
01041
01042
01043 _sayLineDefaults.setFGColor(_savedState->readColor());
01044 _sayLineDefaults.setFont(Font::getPool().getObject(_savedState->readLESint32()));
01045 _sayLineDefaults.setHeight(_savedState->readLESint32());
01046 _sayLineDefaults.setJustify(_savedState->readLESint32());
01047 _sayLineDefaults.setWidth(_savedState->readLESint32());
01048 _sayLineDefaults.setX(_savedState->readLESint32());
01049 _sayLineDefaults.setY(_savedState->readLESint32());
01050 _sayLineDefaults.setDuration(_savedState->readLESint32());
01051 if (_savedState->saveMinorVersion() > 5) {
01052 _movieSubtitle = TextObject::getPool().getObject(_savedState->readLESint32());
01053 }
01054
01055
01056 _currSet = Set::getPool().getObject(_savedState->readLESint32());
01057 if (_savedState->saveMinorVersion() > 4) {
01058 _movieSetup = _savedState->readString();
01059 } else {
01060 _movieSetup = _currSet->getCurrSetup()->_name;
01061 }
01062
01063 _savedState->endSection();
01064 }
01065
01066 void GrimEngine::storeSaveGameImage(SaveGame *state) {
01067 const Graphics::PixelFormat image_format = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
01068 int width = 250, height = 188;
01069 Bitmap *screenshot;
01070
01071 debug("GrimEngine::StoreSaveGameImage() started.");
01072
01073 screenshot = g_driver->getScreenshot(width, height, true);
01074 state->beginSection('SIMG');
01075 if (screenshot) {
01076 int size = screenshot->getWidth() * screenshot->getHeight();
01077 screenshot->setActiveImage(0);
01078 screenshot->getBitmapData()->convertToColorFormat(image_format);
01079 uint16 *data = (uint16 *)screenshot->getData().getRawBuffer();
01080 for (int l = 0; l < size; l++) {
01081 state->writeLEUint16(data[l]);
01082 }
01083 } else {
01084 error("Unable to store screenshot");
01085 }
01086 state->endSection();
01087 delete screenshot;
01088 debug("GrimEngine::StoreSaveGameImage() finished.");
01089 }
01090
01091 void GrimEngine::savegameSave() {
01092 debug("GrimEngine::savegameSave() started.");
01093 _savegameSaveRequest = false;
01094 Common::String filename;
01095 if (_savegameFileName.size() == 0) {
01096 filename = "grim.sav";
01097 } else {
01098 filename = _savegameFileName;
01099 }
01100 if (getGameType() == GType_MONKEY4 && filename.contains('/')) {
01101 filename = Common::lastPathComponent(filename, '/');
01102 }
01103 _savedState = SaveGame::openForSaving(filename);
01104 if (!_savedState) {
01105
01106 GUI::displayErrorDialog("Error: the game could not be saved.");
01107 return;
01108 }
01109
01110 storeSaveGameImage(_savedState);
01111
01112 if (g_imuse)
01113 g_imuse->pause(true);
01114 g_movie->pause(true);
01115
01116 savegameCallback();
01117
01118 Bitmap::getPool().saveObjects(_savedState);
01119 Debug::debug(Debug::Engine, "Bitmaps saved successfully.");
01120
01121 Font::getPool().saveObjects(_savedState);
01122 Debug::debug(Debug::Engine, "Fonts saved successfully.");
01123
01124 ObjectState::getPool().saveObjects(_savedState);
01125 Debug::debug(Debug::Engine, "ObjectStates saved successfully.");
01126
01127 Set::getPool().saveObjects(_savedState);
01128 Debug::debug(Debug::Engine, "Sets saved successfully.");
01129
01130 TextObject::getPool().saveObjects(_savedState);
01131 Debug::debug(Debug::Engine, "TextObjects saved successfully.");
01132
01133 PrimitiveObject::getPool().saveObjects(_savedState);
01134 Debug::debug(Debug::Engine, "PrimitiveObjects saved successfully.");
01135
01136 Actor::getPool().saveObjects(_savedState);
01137 Debug::debug(Debug::Engine, "Actors saved successfully.");
01138
01139 if (getGameType() == GType_MONKEY4) {
01140 PoolSound::getPool().saveObjects(_savedState);
01141 Debug::debug(Debug::Engine, "Pool sounds saved successfully.");
01142
01143 Layer::getPool().saveObjects(_savedState);
01144 Debug::debug(Debug::Engine, "Layers saved successfully.");
01145 }
01146
01147 saveGRIM();
01148 Debug::debug(Debug::Engine, "Engine saved successfully.");
01149
01150 g_driver->saveState(_savedState);
01151 Debug::debug(Debug::Engine, "Renderer saved successfully.");
01152
01153 g_sound->saveState(_savedState);
01154 Debug::debug(Debug::Engine, "iMuse saved successfully.");
01155
01156 g_movie->saveState(_savedState);
01157 Debug::debug(Debug::Engine, "Movie saved successfully.");
01158
01159 _iris->saveState(_savedState);
01160 Debug::debug(Debug::Engine, "Iris saved successfully.");
01161
01162 lua_Save(_savedState);
01163
01164 delete _savedState;
01165
01166 if (g_imuse)
01167 g_imuse->pause(false);
01168 g_movie->pause(false);
01169 debug("GrimEngine::savegameSave() finished.");
01170
01171 _shortFrame = true;
01172 clearEventQueue();
01173 }
01174
01175 void GrimEngine::saveGRIM() {
01176 _savedState->beginSection('GRIM');
01177
01178 _savedState->writeLEUint32((uint32)_mode);
01179 _savedState->writeLEUint32((uint32)_previousMode);
01180
01181
01182 if (_selectedActor) {
01183 _savedState->writeLESint32(_selectedActor->getId());
01184 } else {
01185 _savedState->writeLESint32(0);
01186 }
01187
01188
01189 _savedState->writeColor(_sayLineDefaults.getFGColor());
01190 _savedState->writeLESint32(_sayLineDefaults.getFont()->getId());
01191 _savedState->writeLESint32(_sayLineDefaults.getHeight());
01192 _savedState->writeLESint32(_sayLineDefaults.getJustify());
01193 _savedState->writeLESint32(_sayLineDefaults.getWidth());
01194 _savedState->writeLESint32(_sayLineDefaults.getX());
01195 _savedState->writeLESint32(_sayLineDefaults.getY());
01196 _savedState->writeLESint32(_sayLineDefaults.getDuration());
01197 _savedState->writeLESint32(_movieSubtitle ? _movieSubtitle->getId() : 0);
01198
01199
01200 _savedState->writeLESint32(_currSet->getId());
01201 _savedState->writeString(_movieSetup);
01202
01203 _savedState->endSection();
01204 }
01205
01206 Set *GrimEngine::findSet(const Common::String &name) {
01207
01208 foreach (Set *s, Set::getPool()) {
01209 if (s->getName() == name)
01210 return s;
01211 }
01212 return nullptr;
01213 }
01214
01215 void GrimEngine::setSetLock(const char *name, bool lockStatus) {
01216 Set *scene = findSet(name);
01217
01218 if (!scene) {
01219 Debug::warning(Debug::Engine, "Set object '%s' not found in list", name);
01220 return;
01221 }
01222
01223 scene->_locked = lockStatus;
01224 }
01225
01226 Set *GrimEngine::loadSet(const Common::String &name) {
01227 Set *s = findSet(name);
01228
01229 if (!s) {
01230 Common::String filename(name);
01231
01232 if (g_grim->getGameType() == GType_MONKEY4) {
01233 filename += "b";
01234 }
01235 Common::SeekableReadStream *stream;
01236 stream = g_resourceloader->openNewStreamFile(filename.c_str());
01237 if (!stream)
01238 error("Could not find scene file %s", name.c_str());
01239
01240 s = new Set(name, stream);
01241 delete stream;
01242 }
01243
01244 return s;
01245 }
01246
01247 void GrimEngine::setSet(const char *name) {
01248 setSet(loadSet(name));
01249 }
01250
01251 void GrimEngine::setSet(Set *scene) {
01252 if (scene == _currSet)
01253 return;
01254
01255 if (getGameType() == GType_MONKEY4) {
01256 foreach (PoolSound *s, PoolSound::getPool()) {
01257 s->stop();
01258 }
01259 }
01260
01261
01262
01263 foreach (Actor *a, Actor::getPool()) {
01264 a->stopWalking();
01265 }
01266
01267 Set *lastSet = _currSet;
01268 _currSet = scene;
01269 _currSet->setSoundParameters(20, 127);
01270
01271 if (lastSet && !lastSet->_locked) {
01272 delete lastSet;
01273 }
01274 _shortFrame = true;
01275 _setupChanged = true;
01276 invalidateActiveActorsList();
01277 }
01278
01279 void GrimEngine::makeCurrentSetup(int num) {
01280 int prevSetup = g_grim->getCurrSet()->getSetup();
01281 if (prevSetup != num) {
01282 getCurrSet()->setSetup(num);
01283 getCurrSet()->setSoundParameters(20, 127);
01284 cameraChangeHandle(prevSetup, num);
01285
01286
01287 _setupChanged = true;
01288 }
01289 }
01290
01291 void GrimEngine::setTextSpeed(int speed) {
01292 if (speed < 1)
01293 _textSpeed = 1;
01294 if (speed > 10)
01295 _textSpeed = 10;
01296 _textSpeed = speed;
01297 }
01298
01299 float GrimEngine::getControlAxis(int num) {
01300 int idx = num - KEYCODE_AXIS_JOY1_X;
01301 if (idx >= 0 && idx < NUM_JOY_AXES) {
01302 return _joyAxisPosition[idx];
01303 }
01304 return 0;
01305 }
01306
01307 bool GrimEngine::getControlState(int num) {
01308 return _controlsState[num];
01309 }
01310
01311 float GrimEngine::getPerSecond(float rate) const {
01312 return rate * _frameTime / 1000;
01313 }
01314
01315 void GrimEngine::invalidateActiveActorsList() {
01316 _buildActiveActorsList = true;
01317 }
01318
01319 void GrimEngine::immediatelyRemoveActor(Actor *actor) {
01320 _activeActors.remove(actor);
01321 _talkingActors.remove(actor);
01322 }
01323
01324 void GrimEngine::buildActiveActorsList() {
01325 if (!_buildActiveActorsList) {
01326 return;
01327 }
01328
01329 _activeActors.clear();
01330 foreach (Actor *a, Actor::getPool()) {
01331 if (((_mode == NormalMode || _mode == DrawMode) && a->isDrawableInSet(_currSet->getName())) ||
01332 a->isInOverworld()) {
01333 _activeActors.push_back(a);
01334 }
01335 }
01336 _buildActiveActorsList = false;
01337 }
01338
01339 void GrimEngine::addTalkingActor(Actor *a) {
01340 _talkingActors.push_back(a);
01341 }
01342
01343 bool GrimEngine::areActorsTalking() const {
01344
01345 bool talking = false;
01346 foreach (Actor *a, _talkingActors) {
01347 if (a->isTalkingForeground()) {
01348 talking = true;
01349 break;
01350 }
01351 }
01352 return talking;
01353 }
01354
01355 void GrimEngine::setMovieSubtitle(TextObject *to) {
01356 if (_movieSubtitle != to) {
01357 delete _movieSubtitle;
01358 _movieSubtitle = to;
01359 }
01360 }
01361
01362 void GrimEngine::setMovieSetup() {
01363 _movieSetup = _currSet->getCurrSetup()->_name;
01364 }
01365
01366 void GrimEngine::setMode(EngineMode mode) {
01367 _mode = mode;
01368 invalidateActiveActorsList();
01369 }
01370
01371 void GrimEngine::clearEventQueue() {
01372 Common::Event event;
01373 while (g_system->getEventManager()->pollEvent(event)) {
01374 }
01375
01376 for (int i = 0; i < KEYCODE_EXTRA_LAST; ++i) {
01377 _controlsState[i] = false;
01378 }
01379 }
01380
01381 bool GrimEngine::hasFeature(EngineFeature f) const {
01382 return
01383 (f == kSupportsRTL) ||
01384 (f == kSupportsLoadingDuringRuntime) ||
01385 (f == kSupportsJoystick);
01386 }
01387
01388 void GrimEngine::pauseEngineIntern(bool pause) {
01389 if (g_imuse)
01390 g_imuse->pause(pause);
01391 if (g_movie)
01392 g_movie->pause(pause);
01393
01394 if (pause) {
01395 _pauseStartTime = _system->getMillis();
01396 } else {
01397 _frameStart += _system->getMillis() - _pauseStartTime;
01398 }
01399 }
01400
01401
01402 Graphics::Surface *loadPNG(const Common::String &filename) {
01403 Image::PNGDecoder d;
01404 Common::SeekableReadStream *s = SearchMan.createReadStreamForMember(filename);
01405 if (!s)
01406 return nullptr;
01407 d.loadStream(*s);
01408 delete s;
01409
01410 Graphics::Surface *srf = d.getSurface()->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));
01411 return srf;
01412 }
01413
01414 void GrimEngine::setSideTextures(const Common::String &setup) {
01415 if (! g_system->hasFeature(OSystem::kFeatureSideTextures))
01416 return;
01417 Graphics::Surface *t1 = loadPNG(Common::String::format("%s_left.png", setup.c_str()));
01418 Graphics::Surface *t2 = loadPNG(Common::String::format("%s_right.png", setup.c_str()));
01419 g_system->suggestSideTextures(t1, t2);
01420 if (t1)
01421 t1->free();
01422 if (t2)
01423 t2->free();
01424 delete t1;
01425 delete t2;
01426 }
01427
01428
01429 void GrimEngine::debugLua(const Common::String &str) {
01430 lua_dostring(str.c_str());
01431 }
01432
01433 }