scummvm/engine.cpp

452 lines
11 KiB
C++
Raw Normal View History

2003-08-15 18:00:22 +00:00
// Residual - Virtual machine to run LucasArts' 3D adventure games
2005-01-01 10:23:18 +00:00
// Copyright (C) 2003-2005 The ScummVM-Residual Team (www.scummvm.org)
2003-08-15 18:00:22 +00:00
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "stdafx.h"
#include "engine.h"
#include "scene.h"
#include "lua.h"
#include "colormap.h"
#include "actor.h"
#include "textobject.h"
#include "smush.h"
#include "driver.h"
2005-01-01 12:27:57 +00:00
2004-12-30 22:38:53 +00:00
#include "imuse/imuse.h"
2004-04-20 17:49:12 +00:00
2005-01-01 12:27:57 +00:00
#include <SDL.h>
#include <SDL_timer.h>
#include <assert.h>
2003-08-15 18:00:22 +00:00
Engine *g_engine = NULL;
2003-08-15 18:00:22 +00:00
2004-12-30 22:38:53 +00:00
extern Imuse *g_imuse;
2005-01-03 16:27:57 +00:00
int g_imuseState = -1;
2004-12-30 22:38:53 +00:00
2005-04-08 17:32:02 +00:00
#ifdef _MSC_VER
WIN32_FIND_DATAA g_find_file_data;
HANDLE g_searchFile;
bool g_firstFind;
#else
DIR *g_searchFile;
#endif
// hack for access current upated actor to allow access position of actor to sound costume component
Actor *g_currentUpdatedActor = NULL;
2003-08-15 18:00:22 +00:00
Engine::Engine() :
2004-12-09 23:55:43 +00:00
_currScene(NULL), _selectedActor(NULL) {
for (int i = 0; i < SDLK_EXTRA_LAST; i++)
2004-12-09 23:55:43 +00:00
_controlsEnabled[i] = false;
_speechMode = 3; // VOICE + TEXT
2005-04-08 06:50:09 +00:00
_menuMode = 0;
2005-04-08 11:47:47 +00:00
_textSpeed = 6;
2005-04-08 17:32:02 +00:00
g_searchFile = NULL;
textObjectDefaults.x = 0;
textObjectDefaults.y = 200;
textObjectDefaults.width = 10;
textObjectDefaults.height = 0;
textObjectDefaults.fgColor._vals[0] = 255;
textObjectDefaults.fgColor._vals[1] = 255;
textObjectDefaults.fgColor._vals[2] = 255;
textObjectDefaults.font = NULL;
textObjectDefaults.justify = 2;
sayLineDefaults.x = 0;
sayLineDefaults.y = 100;
sayLineDefaults.width = 0;
sayLineDefaults.height = 0;
sayLineDefaults.fgColor._vals[0] = 255;
sayLineDefaults.fgColor._vals[1] = 255;
sayLineDefaults.fgColor._vals[2] = 255;
sayLineDefaults.font = NULL;
sayLineDefaults.justify = 1;
printLineDefaults.x = 0;
printLineDefaults.y = 100;
printLineDefaults.width = 0;
printLineDefaults.height = 0;
printLineDefaults.fgColor._vals[0] = 255;
printLineDefaults.fgColor._vals[1] = 255;
printLineDefaults.fgColor._vals[2] = 255;
printLineDefaults.font = NULL;
2005-03-20 16:54:42 +00:00
printLineDefaults.justify = 2;
2003-08-15 18:00:22 +00:00
}
void Engine::handleButton(int operation, int key) {
lua_beginblock();
lua_Object menu = getEventHandler("menuHandler");
if (menu != LUA_NOOBJECT && !lua_isnil(menu)) {
lua_Object system_table = lua_getglobal("system");
lua_pushobject(system_table);
lua_pushstring(const_cast<char *>("userPaintHandler"));
lua_pushobject(lua_gettable());
lua_pushnumber(key);
if (operation == SDL_KEYDOWN)
lua_pushnil();
else
lua_pushnumber(1);
lua_pushnil();
lua_callfunction(menu);
}
lua_endblock();
lua_beginblock();
lua_Object handler = getEventHandler("buttonHandler");
if (handler != LUA_NOOBJECT) {
lua_pushnumber(key);
if (operation == SDL_KEYDOWN)
lua_pushnumber(1);
else
lua_pushnil();
lua_pushnil();
lua_callfunction(handler);
}
lua_endblock();
}
2003-08-15 18:00:22 +00:00
void Engine::mainLoop() {
2004-12-09 23:55:43 +00:00
_movieTime = 0;
_frameTime = 0;
_frameStart = SDL_GetTicks();
2004-04-15 20:20:04 +00:00
unsigned int frameCounter = 0;
unsigned int timeAccum = 0;
unsigned int frameTimeCollection = 0;
2004-04-15 20:20:04 +00:00
char fps[8] = "";
2004-11-01 09:47:19 +00:00
_savegameLoadRequest = false;
_savegameSaveRequest = false;
_savegameFileName = NULL;
for (;;) {
// Process events
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_KEYDOWN && _controlsEnabled[event.key.keysym.sym])
handleButton(SDL_KEYDOWN, event.key.keysym.sym);
2004-12-09 23:55:43 +00:00
if (event.type == SDL_KEYUP && _controlsEnabled[event.key.keysym.sym]) {
handleButton(SDL_KEYUP, event.key.keysym.sym);
}
if (event.type == SDL_QUIT) {
lua_beginblock();
lua_Object handler = getEventHandler("exitHandler");
if (handler != LUA_NOOBJECT)
lua_callfunction(handler);
lua_endblock();
}
if (event.type == SDL_KEYDOWN) {
2005-03-28 01:54:21 +00:00
if ((event.key.keysym.sym == SDLK_RETURN ||
event.key.keysym.sym == SDLK_KP_ENTER) &&
(event.key.keysym.mod & KMOD_ALT))
2005-04-08 10:23:03 +00:00
g_driver->toggleFullscreenMode();
if (event.key.keysym.sym == SDLK_q)
return;
}
}
2004-11-01 16:36:41 +00:00
if (_savegameLoadRequest) {
savegameRestore();
}
if (_savegameSaveRequest) {
savegameSave();
}
if (_mode == ENGINE_MODE_SMUSH) {
if (g_smush->isPlaying()) {
2004-12-09 23:55:43 +00:00
_movieTime = g_smush->getMovieTime();
if (g_smush->isUpdateNeeded()) {
g_driver->prepareSmushFrame(g_smush->getWidth(), g_smush->getHeight(), g_smush->getDstPtr());
g_smush->clearUpdateNeeded();
}
2004-04-19 11:56:46 +00:00
if (g_smush->getFrame() > 0) {
g_driver->drawSmushFrame(g_smush->getX(), g_smush->getY());
2004-04-19 11:56:46 +00:00
if (SHOWFPS_GLOBAL)
g_driver->drawEmergString(550, 25, fps, Color(255, 255, 255));
}
}
} else if (_mode == ENGINE_MODE_NORMAL) {
g_driver->clearScreen();
// Update actor costumes
for (ActorListType::iterator i = _actors.begin(); i != _actors.end(); i++) {
Actor *a = *i;
g_currentUpdatedActor = *i;
if (_currScene != NULL && a->inSet(_currScene->name()) && a->visible())
a->update();
}
g_currentUpdatedActor = NULL;
2004-12-09 23:55:43 +00:00
if (_currScene != NULL) {
_currScene->drawBackground();
2004-03-22 11:23:37 +00:00
}
if (g_smush->isPlaying()) {
2004-12-09 23:55:43 +00:00
_movieTime = g_smush->getMovieTime();
if (g_smush->isUpdateNeeded()) {
g_driver->prepareSmushFrame(g_smush->getWidth(), g_smush->getHeight(), g_smush->getDstPtr());
g_smush->clearUpdateNeeded();
}
if (g_smush->getFrame() > 0)
g_driver->drawSmushFrame(g_smush->getX(), g_smush->getY());
}
2004-12-09 23:55:43 +00:00
if (_currScene != NULL) {
_currScene->drawBitmaps(ObjectState::OBJSTATE_UNDERLAY);
_currScene->drawBitmaps(ObjectState::OBJSTATE_STATE);
_currScene->drawBitmaps(ObjectState::OBJSTATE_OVERLAY);
}
2004-04-20 18:54:04 +00:00
if (SHOWFPS_GLOBAL)
g_driver->drawEmergString(550, 25, fps, Color(255, 255, 255));
2004-12-09 23:55:43 +00:00
if (_currScene != NULL) {
_currScene->setupCamera();
}
g_driver->set3DMode();
if (_currScene != NULL) {
_currScene->setupLights();
}
2005-01-11 19:59:40 +00:00
// Draw actors
for (ActorListType::iterator i = _actors.begin(); i != _actors.end(); i++) {
Actor *a = *i;
if (_currScene != NULL && a->inSet(_currScene->name()) && a->visible())
a->draw();
if (_currScene != NULL)
a->undraw(a->inSet(_currScene->name()) && a->visible());
}
}
2003-08-30 17:58:33 +00:00
2005-04-07 19:29:06 +00:00
// Draw Primitives
for (PrimitiveListType::iterator i = _primitiveObjects.begin(); i != _primitiveObjects.end(); i++) {
(*i)->draw();
}
// Draw text
for (TextListType::iterator i = _textObjects.begin(); i != _textObjects.end(); i++) {
(*i)->draw();
}
2004-12-31 20:11:09 +00:00
g_imuse->flushTracks();
g_imuse->refreshScripts();
2004-04-20 17:49:12 +00:00
g_driver->flipBuffer();
// don't kill CPU
SDL_Delay(1);
// Update timing information
unsigned newStart = SDL_GetTicks();
2004-12-09 23:55:43 +00:00
_frameTime = newStart - _frameStart;
_frameStart = newStart;
2004-12-09 23:55:43 +00:00
frameTimeCollection += _frameTime;
if (frameTimeCollection > 10000) {
frameTimeCollection = 0;
lua_collectgarbage(0);
}
lua_beginblock();
2004-12-10 07:26:03 +00:00
setFrameTime(_frameTime);
lua_endblock();
lua_beginblock();
2004-12-10 07:26:03 +00:00
setMovieTime(_movieTime);
lua_endblock();
2004-04-15 20:39:09 +00:00
if (SHOWFPS_GLOBAL) {
frameCounter++;
2004-12-09 23:55:43 +00:00
timeAccum += _frameTime;
2004-04-15 20:39:09 +00:00
if (timeAccum > 1000) {
sprintf(fps, "%7.2f", (double)(frameCounter * 1000) / (double)timeAccum );
frameCounter = 0;
timeAccum = 0;
}
}
2005-04-08 06:50:09 +00:00
if (!_menuMode)
// Run asynchronous tasks
lua_runtasks();
2005-01-03 16:27:57 +00:00
if (g_imuseState != -1) {
g_imuse->setMusicState(g_imuseState);
g_imuseState = -1;
}
}
2003-08-15 18:00:22 +00:00
}
void Engine::savegameGzread(void *data, int size) {
gzread(g_engine->_savegameFileHandle, data, size);
2004-11-01 16:36:41 +00:00
}
void Engine::savegameGzwrite(void *data, int size) {
gzwrite(g_engine->_savegameFileHandle, data, size);
2004-11-01 16:36:41 +00:00
}
void Engine::savegameRestore() {
printf("Engine::savegameRestore() started.\n");
2004-11-01 16:36:41 +00:00
_savegameLoadRequest = false;
char filename[200];
if (_savegameFileName == NULL) {
strcpy(filename, "grim.sav");
} else {
strcpy(filename, _savegameFileName);
}
_savegameFileHandle = gzopen(filename, "rb");
if (_savegameFileHandle == NULL) {
warning("savegameRestore() Error opening savegame file");
return;
}
2004-12-30 22:38:53 +00:00
g_imuse->stopAllSounds();
2004-12-30 23:48:04 +00:00
g_imuse->resetState();
2004-11-01 16:36:41 +00:00
g_smush->stop();
2005-01-14 10:53:29 +00:00
g_imuse->pause(true);
g_smush->pause(true);
2004-11-01 16:36:41 +00:00
// free all resource
// lock resources
2005-01-12 13:48:29 +00:00
uint32 tag;
uint32 version;
savegameGzread(&tag, 4);
assert(tag == 'RSAV');
savegameGzread(&version, 4);
assert(version == 1);
2004-11-01 16:36:41 +00:00
//Chore_Restore(savegameGzread);
//Resource_Restore(savegameGzread);
//Text_Restore(savegameGzread);
//Room_Restore(savegameGzread);
//Actor_Restore(savegameGzread);
//Render_Restore(savegameGzread);
//Primitive_Restore(savegameGzread);
//Smush_Restore(savegameGzread);
2005-01-12 13:48:29 +00:00
g_imuse->restoreState(savegameGzread);
lua_Restore(savegameGzread);
2004-11-01 16:36:41 +00:00
// unlock resources
gzclose(_savegameFileHandle);
//bundle_dofile("patch05.bin");
2004-11-01 17:34:48 +00:00
2005-01-14 10:53:29 +00:00
g_imuse->pause(false);
g_smush->pause(false);
printf("Engine::savegameRestore() finished.\n");
2004-11-01 16:36:41 +00:00
}
void Engine::savegameSave() {
printf("Engine::savegameSave() started.\n");
2004-11-01 16:36:41 +00:00
_savegameSaveRequest = false;
char filename[200];
if (_savegameFileName == NULL) {
strcpy(filename, "grim.sav");
} else {
strcpy(filename, _savegameFileName);
}
_savegameFileHandle = gzopen(filename, "wb");
if (_savegameFileHandle == NULL) {
warning("savegameSave() Error creating savegame file");
return;
}
g_imuse->pause(true);
g_smush->pause(true);
2005-01-12 13:48:29 +00:00
uint32 tag = 'RSAV';
uint32 version = 1;
savegameGzwrite(&tag, 4);
savegameGzwrite(&version, 4);
2005-01-12 23:28:47 +00:00
savegameCallback();
2004-11-01 16:36:41 +00:00
//Chore_Save(savegameGzwrite);
//Resource_Save(savegameGzwrite);
//Text_Save(savegameGzwrite);
//Room_Save(savegameGzwrite);
//Actor_Save(savegameGzwrite);
//Render_Save(savegameGzwrite);
//Primitive_Save(savegameGzwrite);
//Smush_Save(savegameGzwrite);
2005-01-12 13:48:29 +00:00
g_imuse->saveState(savegameGzread);
lua_Save(savegameGzwrite);
2004-11-01 16:36:41 +00:00
gzclose(_savegameFileHandle);
g_imuse->pause(false);
g_smush->pause(false);
printf("Engine::savegameSave() finished.\n");
2004-11-01 16:36:41 +00:00
}
2005-01-14 10:53:29 +00:00
void Engine::savegameCallback() {
lua_Object funcParam1;
lua_Object funcParam2;
bool unk1 = false;
bool unk2 = false;
lua_beginblock();
lua_pushobject(lua_getglobal("system"));
lua_pushstring("saveGameCallback");
funcParam2 = lua_gettable();
if (lua_istable(funcParam2)) {
lua_pushobject(funcParam2);
lua_pushstring("saveGameCallback");
funcParam1 = lua_gettable();
if (lua_isfunction(funcParam1)) {
unk1 = true;
unk2 = true;
} else {
assert(false);
}
} else if (lua_isfunction(funcParam2)) {
funcParam1 = funcParam2;
unk1 = false;
unk2 = true;
} else if (!lua_isnil(funcParam2)) {
assert(false);
}
if (unk2) {
if (unk1) {
lua_pushobject(funcParam2);
}
lua_callfunction(funcParam1);
}
lua_endblock();
}
2003-08-15 18:00:22 +00:00
void Engine::setScene(const char *name) {
Block *b = g_resourceloader->getFileBlock(name);
if (b == NULL)
warning("Could not find scene file %s\n", name);
2004-12-09 23:55:43 +00:00
delete _currScene;
_currScene = new Scene(name, b->data(), b->len());
2005-01-05 18:28:50 +00:00
_currScene->setSoundParameters(20, 127);
delete b;
2003-08-15 18:00:22 +00:00
}
2005-04-08 11:47:47 +00:00
void Engine::setTextSpeed(int speed) {
if (speed < 1)
_textSpeed = 1;
if (speed > 10)
_textSpeed = 10;
_textSpeed = speed;
}