diff options
Diffstat (limited to 'engines/toltecs/toltecs.cpp')
-rw-r--r-- | engines/toltecs/toltecs.cpp | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/engines/toltecs/toltecs.cpp b/engines/toltecs/toltecs.cpp new file mode 100644 index 0000000000..78f3e23afe --- /dev/null +++ b/engines/toltecs/toltecs.cpp @@ -0,0 +1,483 @@ +/* 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/events.h" +#include "common/keyboard.h" +#include "common/file.h" +#include "common/savefile.h" +#include "common/config-manager.h" +#include "common/str.h" + +#include "base/plugins.h" +#include "base/version.h" + +#include "graphics/surface.h" +#include "graphics/cursorman.h" +#include "graphics/primitives.h" + +#include "sound/mixer.h" + +#include "toltecs/toltecs.h" +#include "toltecs/animation.h" +#include "toltecs/input.h" +#include "toltecs/palette.h" +#include "toltecs/resource.h" +#include "toltecs/script.h" +#include "toltecs/screen.h" +#include "toltecs/segmap.h" + +namespace Toltecs { + +struct GameSettings { + const char *gameid; + const char *description; + byte id; + uint32 features; + const char *detectname; +}; + +ToltecsEngine::ToltecsEngine(OSystem *syst, const ToltecsGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { + + // Setup mixer + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); + + _rnd = new Common::RandomSource(); + syst->getEventManager()->registerRandomSource(*_rnd, "toltecs"); + + int cd_num = ConfMan.getInt("cdrom"); + if (cd_num >= 0) + _system->openCD(cd_num); + +} + +ToltecsEngine::~ToltecsEngine() { + delete _rnd; +} + +int ToltecsEngine::init() { + // Initialize backend + _system->beginGFXTransaction(); + initCommonGFX(false); + _system->initSize(640, 400); + _system->endGFXTransaction(); + return 0; +} + +int ToltecsEngine::go() { + + _system->setFeatureState(OSystem::kFeatureAutoComputeDirtyRects, true); + + _quitGame = false; + _counter01 = 0; + _counter02 = 0; + _movieSceneFlag = false; + _flag01 = 0; + + _cameraX = 0; + _cameraY = 0; + _newCameraX = 0; + _newCameraY = 0; + _cameraTop = 26; + _cameraHeight = 0; + _yetAnotherX = 0; + + _sceneWidth = 0; + _sceneHeight = 0; + + _doSpeech = true; + _doText = true; + + _walkSpeedY = 5; + _walkSpeedX = 1; + + _arc = new ArchiveReader(); + _arc->openArchive("WESTERN"); + + _res = new ResourceCache(this); + + _screen = new Screen(this); + + _script = new ScriptInterpreter(this); + _anim = new AnimationPlayer(this); + _palette = new Palette(this); + _segmap = new SegmentMap(this); + _input = new Input(this); + + _system->showMouse(true); + +#if 1 + + _script->loadScript(0, 0); + _script->runScript(0); + +#endif + + delete _arc; + delete _res; + delete _screen; + delete _script; + delete _anim; + delete _palette; + delete _segmap; + delete _input; + + return 0; +} + +void ToltecsEngine::loadScene(uint resIndex) { + // TODO + + byte *scene = _res->load(resIndex); + + uint32 imageSize = READ_LE_UINT32(scene); + _sceneResIndex = resIndex; + _sceneHeight = READ_LE_UINT16(scene + 4); + _sceneWidth = READ_LE_UINT16(scene + 6); + + // Load scene palette + _palette->loadAddPaletteFrom(scene + 8, 0, 128); + + // Load scene background + byte *source = scene + 392; + byte *destp = _screen->_backScreen; + byte *destEnd = destp + _sceneWidth * _sceneHeight; + while (destp < destEnd) { + int count = 1; + byte pixel = *source++; + if (pixel & 0x80) { + pixel &= 0x7F; + count = *source++; + count += 2; + } + memset(destp, pixel, count); + destp += count; + } + + debug(0, "_sceneWidth = %d; _sceneHeight = %d", _sceneWidth, _sceneHeight); + + // Load scene segmap + _segmap->load(scene + imageSize + 4); + +} + +void ToltecsEngine::updateScreen() { + // TODO + + byte *destp = _screen->_frontScreen; + byte *srcp = _screen->_backScreen + _cameraX + _cameraY * _sceneWidth; + for (uint y = 0; y < MIN<uint>(_cameraHeight, 400); y++) { + memcpy(destp, srcp, MIN<uint>(_sceneWidth, 640)); + destp += 640; + srcp += _sceneWidth; + } + + _screen->drawSprites(); + _screen->clearSprites(); + + _screen->drawTalkTextItems(); + + _system->copyRectToScreen((const byte *)_screen->_frontScreen, 640, 0, 0, 640, 400); + _system->updateScreen(); + + updateCamera(); +} + +void ToltecsEngine::setCamera(int16 x, int16 y) { + + // TODO font_sub_4B5BB() + + if (x > _sceneWidth) + x = _sceneWidth; + + if (y > _sceneHeight - _cameraHeight) + y = _sceneHeight - _cameraHeight; + + // TODO DirtyRect clearing stuff + + _screen->clearSprites(); + + _cameraX = x; + _newCameraX = x; + + _cameraY = y; + _newCameraY = y; + + // TODO More DirtyRect clearing stuff + +} + +void ToltecsEngine::setCameraTop(int16 top) { + if (top != _cameraTop) { + _cameraTop = top; + _cameraHeight = 400 - _cameraTop; + debug(0, "ToltecsEngine::setCameraTop() _cameraTop = %d; _cameraHeight = %d", _cameraTop, _cameraHeight); + // TODO: clearScreen(); + } +} + +void ToltecsEngine::scrollCameraUp(int16 delta) { + if (_newCameraY > 0) { + if (_newCameraY < delta) + _newCameraY = 0; + else + _newCameraY -= delta; + // TODO: font_sub_4B5BB(); + } +} + +void ToltecsEngine::scrollCameraDown(int16 delta) { + debug(0, "ToltecsEngine::scrollCameraDown(%d)", delta); + if (_newCameraY != _sceneHeight - _cameraHeight) { + if (_sceneHeight - _cameraHeight < _newCameraY + delta) + delta += (_sceneHeight - _cameraHeight) - (delta + _newCameraY); + _newCameraY += delta; + debug(0, "ToltecsEngine::scrollCameraDown() _newCameraY = %d; delta = %d", _newCameraY, delta); + // TODO: font_sub_4B5BB(); + } +} + +void ToltecsEngine::scrollCameraLeft(int16 delta) { + if (_newCameraX > 0) { + if (_newCameraX < delta) + _newCameraX = 0; + else + _newCameraX -= delta; + // TODO: font_sub_4B5BB(); + } +} + +void ToltecsEngine::scrollCameraRight(int16 delta) { + debug(0, "ToltecsEngine::scrollCameraRight(%d)", delta); + if (_newCameraX != _sceneWidth - 640) { + if (_sceneWidth - 640 < delta + _newCameraX) + delta += (_sceneWidth - 640) - (delta + _newCameraX); + _newCameraX += delta; + debug(0, "ToltecsEngine::scrollCameraRight() _newCameraX = %d; delta = %d", _newCameraY, delta); + // TODO: font_sub_4B5BB(); + } +} + +void ToltecsEngine::updateCamera() { + + _yetAnotherX = _newCameraX; + if (_cameraX != _yetAnotherX) { + //dirtyFullRefresh = -1; + } + _cameraX = _yetAnotherX; + + if (_cameraY != _newCameraY) { + if (_cameraY < _newCameraY) { + /* + drawRequest.resIndex = -(cameraY - anotherY); + drawRequest.y = cameraHeight + cameraY; + drawRequest.x = cameraX; + drawRequest.flags = 640; + */ + debug(0, "ToltecsEngine::updateCamera() a: (%d, %d, %d, %d)", + -(_cameraY - _newCameraY), _cameraHeight + _cameraY, _cameraX, 640); + //dirtyFullRefresh = -1; + } else { + /* + drawRequest.resIndex = cameraY - anotherY; + drawRequest.y = anotherY; + drawRequest.x = cameraX; + drawRequest.flags = 640; + */ + debug(0, "ToltecsEngine::updateCamera() b: (%d, %d, %d, %d)", + _cameraY - _newCameraY, _newCameraY, _cameraX, 640); + //dirtyFullRefresh = -1; + } + } + _cameraY = _newCameraY; + + debug(0, "ToltecsEngine::checkCamera() _cameraX = %d; _cameraY = %d", _cameraX, _cameraY); + +} + +void ToltecsEngine::talk(int16 slotIndex, int16 slotOffset) { + + byte *scanData = _script->getSlotData(slotIndex) + slotOffset; + + while (*scanData < 0xF0) { + + if (*scanData == 0x19) { + scanData++; + } else if (*scanData == 0x14) { + scanData++; + } else if (*scanData == 0x0A) { + scanData += 4; + } else if (*scanData < 0x0A) { + scanData++; + } + + scanData++; + } + + if (*scanData == 0xFE) { + if (_doSpeech) { + int16 resIndex = READ_LE_UINT16(scanData + 1); + debug(0, "ToltecsEngine::talk() playSound(resIndex: %d)", resIndex); + } + if (_doText) { + _screen->updateTalkText(slotIndex, slotOffset); + } else { + // TODO: font_sub_4B3E2 + } + } else { + _screen->updateTalkText(slotIndex, slotOffset); + } + +} + +void ToltecsEngine::playText(int16 slotIndex, int16 slotOffset) { + + byte *textData = _script->getSlotData(slotIndex) + slotOffset; + + debug(0, "ToltecsEngine::playText() [textData = %s]", (char*)textData); + + Common::String str; + while (*textData < 0xF0) { + if (*textData >= 32) + str += (char)*textData; + textData++; + } + + debug(0, "ToltecsEngine::playText() [%s]", str.c_str()); + +} + +void ToltecsEngine::walk(byte *walkData) { + + int16 xdelta, ydelta, v8, v10, v11; + int16 xstep, ystep; + ScriptWalk walkInfo; + + walkInfo.y = READ_LE_UINT16(walkData + 0); + walkInfo.x = READ_LE_UINT16(walkData + 2); + walkInfo.y1 = READ_LE_UINT16(walkData + 4); + walkInfo.x1 = READ_LE_UINT16(walkData + 6); + walkInfo.y2 = READ_LE_UINT16(walkData + 8); + walkInfo.x2 = READ_LE_UINT16(walkData + 10); + walkInfo.yerror = READ_LE_UINT16(walkData + 12); + walkInfo.xerror = READ_LE_UINT16(walkData + 14); + walkInfo.mulValue = READ_LE_UINT16(walkData + 16); + walkInfo.scaling = READ_LE_UINT16(walkData + 18); + + walkInfo.scaling = -_segmap->getScalingAtPoint(walkInfo.x, walkInfo.y); + + if (walkInfo.y1 < walkInfo.y2) + ystep = -1; + else + ystep = 1; + ydelta = ABS(walkInfo.y1 - walkInfo.y2) * _walkSpeedY; + + if (walkInfo.x1 < walkInfo.x2) + xstep = -1; + else + xstep = 1; + xdelta = ABS(walkInfo.x1 - walkInfo.x2) * _walkSpeedX; + + debug(0, "ToltecsEngine::walk() xdelta = %d; ydelta = %d", xdelta, ydelta); + + if (xdelta > ydelta) + SWAP(xdelta, ydelta); + + v8 = 100 * xdelta; + if (v8 != 0) { + if (walkInfo.scaling > 0) + v8 -= v8 * ABS(walkInfo.scaling) / 100; + else + v8 += v8 * ABS(walkInfo.scaling) / 100; + if (ydelta != 0) + v8 /= ydelta; + } + + if (ydelta > ABS(walkInfo.x1 - walkInfo.x2) * _walkSpeedX) { + v10 = 100 - walkInfo.scaling; + v11 = v8; + } else { + v10 = v8; + v11 = 100 - walkInfo.scaling; + } + + walkInfo.yerror += walkInfo.mulValue * v10; + while (walkInfo.yerror >= 100 * _walkSpeedY) { + walkInfo.yerror -= 100 * _walkSpeedY; + if (walkInfo.y == walkInfo.y1) { + walkInfo.x = walkInfo.x1; + break; + } + walkInfo.y += ystep; + } + + walkInfo.xerror += walkInfo.mulValue * v11; + while (walkInfo.xerror >= 100 * _walkSpeedX) { + walkInfo.xerror -= 100 * _walkSpeedX; + if (walkInfo.x == walkInfo.x1) { + walkInfo.y = walkInfo.y1; + break; + } + walkInfo.x += xstep; + } + + WRITE_LE_UINT16(walkData + 0, walkInfo.y); + WRITE_LE_UINT16(walkData + 2, walkInfo.x); + WRITE_LE_UINT16(walkData + 4, walkInfo.y1); + WRITE_LE_UINT16(walkData + 6, walkInfo.x1); + WRITE_LE_UINT16(walkData + 8, walkInfo.y2); + WRITE_LE_UINT16(walkData + 10, walkInfo.x2); + WRITE_LE_UINT16(walkData + 12, walkInfo.yerror); + WRITE_LE_UINT16(walkData + 14, walkInfo.xerror); + WRITE_LE_UINT16(walkData + 16, walkInfo.mulValue); + WRITE_LE_UINT16(walkData + 18, walkInfo.scaling); + +} + +int16 ToltecsEngine::findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize) { + + rectData += index * itemSize; + + while (1) { + int16 rectY = READ_LE_UINT16(rectData); + if (rectY == -10) + break; + int16 rectX = READ_LE_UINT16(rectData + 2); + int16 rectH = READ_LE_UINT16(rectData + 4); + int16 rectW = READ_LE_UINT16(rectData + 6); + + debug(0, "x = %d; y = %d; x1 = %d; y2 = %d; w = %d; h = %d", + x, y, rectX, rectY, rectW, rectH); + + if (x >= rectX && x <= rectX + rectW && y >= rectY && y <= rectY + rectH) { + return index; + } + index++; + rectData += itemSize; + } + + return -1; + +} + +} // End of namespace Toltecs |