diff options
-rw-r--r-- | engines/sherlock/objects.cpp | 37 | ||||
-rw-r--r-- | engines/sherlock/objects.h | 26 | ||||
-rw-r--r-- | engines/sherlock/scene.cpp | 196 | ||||
-rw-r--r-- | engines/sherlock/scene.h | 48 | ||||
-rw-r--r-- | engines/sherlock/screen.cpp | 2 | ||||
-rw-r--r-- | engines/sherlock/screen.h | 3 | ||||
-rw-r--r-- | engines/sherlock/sherlock.cpp | 1 | ||||
-rw-r--r-- | engines/sherlock/sherlock.h | 2 | ||||
-rw-r--r-- | engines/sherlock/sound.cpp | 4 | ||||
-rw-r--r-- | engines/sherlock/sound.h | 1 |
10 files changed, 308 insertions, 12 deletions
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 73e6397b50..aa9b391f96 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -134,7 +134,7 @@ void Object::synchronize(Common::SeekableReadStream &s) { _maxFrames = s.readUint16LE(); _flags = s.readByte(); _aOpen.synchronize(s); - _aType = s.readByte(); + _aType = (AType)s.readByte(); _lookFrames = s.readByte(); _seqCounter = s.readByte(); _lookPosition.x = s.readUint16LE(); @@ -155,6 +155,41 @@ void Object::synchronize(Common::SeekableReadStream &s) { _use[idx].synchronize(s); } +void Object::toggleHidden() { + if (_type != HIDDEN && _type != HIDE_SHAPE && _type != INVALID) { + if (_seqTo != 0) + _sequences[_frameNumber] = _seqTo + SEQ_TO_CODE + 128; + _seqTo = 0; + + if (_images == nullptr || _images->size() == 0) + // No shape to erase, so flag as hidden + _type = HIDDEN; + else + // Otherwise, flag it to be hidden after it gets erased + _type = HIDE_SHAPE; + } else if (_type != INVALID) { + if (_seqTo != 0) + _sequences[_frameNumber] = _seqTo + SEQ_TO_CODE + 128; + _seqTo = 0; + + _seqCounter = _seqcounter2 = 0; + _seqStack = 0; + _frameNumber = -1; + + if (_images == nullptr || _images->size() == 0) { + _type = NO_SHAPE; + } else { + _type = ACTIVE_BG_SHAPE; + int idx = _sequences[0]; + if (idx >= _maxFrames) + // Turn on: set up first frame + idx = 0; + + _imageFrame = &(*_images)[idx]; + } + } +} + /*----------------------------------------------------------------*/ void CAnim::synchronize(Common::SeekableReadStream &s) { diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 31d9520932..f3879b1143 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -49,9 +49,31 @@ enum SpriteType { HIDE_SHAPE = 8 // Object needs to be hidden }; +enum AType { + OBJECT = 0, + PERSON = 1, + SOLID = 2, + TALK = 3, // Standard talk zone + FLAG_SET = 4, + DELTA = 5, + WALK_AROUND = 6, + TALK_EVERY = 7, // Talk zone that turns on every room visit + TALK_MOVE = 8, // Talk zone that only activates when Holmes moves + PAL_CHANGE = 9, // Changes the palette down so that it gets darker + PAL_CHANGE2 = 10, // Same as PAL_CHANGE, except that it goes up + SCRIPT_ZONE = 11, // If this is clicked in, it is activated + BLANK_ZONE = 12, // This masks out other objects when entered + NOWALK_ZONE = 13 // Player cannot walk here +}; + #define MAX_HOLMES_SEQUENCE 16 #define MAX_FRAME 30 +// code put into sequences to defines 1-10 type seqs +#define SEQ_TO_CODE 67 +#define FLIP_CODE (64 + 128) +#define SOUND_CODE (34 + 128) + struct Sprite { Common::String _name; // Name Common::String _description; // Description @@ -131,7 +153,7 @@ struct Object { int _maxFrames; // Number of frames int _flags; // Tells if object can be walked behind ActionType _aOpen; // Holds data for moving object - int _aType; // Tells if this is an object, person, talk, etc. + AType _aType; // Tells if this is an object, person, talk, etc. int _lookFrames; // How many frames to play of the look anim before pausing int _seqCounter; // How many times this sequence has been executed Common::Point _lookPosition; // Where to walk when examining object @@ -147,6 +169,8 @@ struct Object { UseType _use[4]; void synchronize(Common::SeekableReadStream &s); + + void toggleHidden(); }; struct CAnim { diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index ffae6f60c1..86e347d011 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -46,18 +46,47 @@ void BgfileheaderInfo::synchronize(Common::SeekableReadStream &s) { _filename = Common::String(buffer); } -int _fSize; // How long images are -int _maxFrames; // How many unique frames in object -Common::String _filename; // Filename of object +/*----------------------------------------------------------------*/ + +void Exit::synchronize(Common::SeekableReadStream &s) { + _position.x = s.readSint16LE(); + _position.y = s.readSint16LE(); + _size.x = s.readSint16LE(); + _size.y = s.readSint16LE(); + _scene = s.readSint16LE(); + _allow = s.readSint16LE(); + _people.x = s.readSint16LE(); + _people.y = s.readSint16LE(); + _peopleDir = s.readUint16LE(); +} + +/*----------------------------------------------------------------*/ + +void SceneEntry::synchronize(Common::SeekableReadStream &s) { + _startPosition.x = s.readSint16LE(); + _startPosition.y = s.readSint16LE(); + _startDir = s.readByte(); + _allow = s.readByte(); +} + +void SceneSound::synchronize(Common::SeekableReadStream &s) { + char buffer[9]; + s.read(buffer, 8); + buffer[8] = '\0'; + + _name = Common::String(buffer); + _priority = s.readByte(); +} /*----------------------------------------------------------------*/ Scene::Scene(SherlockEngine *vm): _vm(vm) { for (int idx = 0; idx < SCENES_COUNT; ++idx) Common::fill(&_stats[idx][0], &_stats[idx][9], false); + _currentScene = -1; _goToRoom = -1; + _changes = false; _oldCharPoint = 0; - _numExits = 0; _windowOpen = _infoFlag = false; _menuMode = _keyboardInput = 0; _walkedInScene = false; @@ -66,10 +95,12 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _lzwMode = false; _invGraphicItems = 0; + _controlPanel = new ImageFile("controls.vgs"); _controls = nullptr; // new ImageFile("menu.all"); } Scene::~Scene() { + delete _controlPanel; delete _controls; clear(); } @@ -78,13 +109,10 @@ Scene::~Scene() { * Takes care of clearing any scene data */ void Scene::clear() { - for (uint idx = 0; idx < _bgShapes.size(); ++idx) - delete _bgShapes[idx]._images; } void Scene::selectScene() { // Reset fields - _numExits = 0; _windowOpen = _infoFlag = false; _menuMode = _keyboardInput = 0; _oldKey = _help = _oldHelp = 0; @@ -93,6 +121,7 @@ void Scene::selectScene() { // Load the scene Common::String sceneFile = Common::String::format("res%02d", _goToRoom); Common::String roomName = Common::String::format("res%02d.rrm", _goToRoom); + _currentScene = _goToRoom; _goToRoom = -1; loadScene(sceneFile); @@ -108,6 +137,8 @@ void Scene::selectScene() { * that it should point to after loading; _misc is then set to 0. */ void Scene::loadScene(const Common::String &filename) { + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; bool flag; _walkedInScene = false; @@ -240,11 +271,160 @@ void Scene::loadScene(const Common::String &filename) { // Back at version byte, so skip over it rrmStream->skip(1); - // TODO + // Load the walk directory + for (int idx1 = 0; idx1 < MAX_ZONES; ++idx1) { + for (int idx2 = 0; idx2 < MAX_ZONES; ++idx2) + _walkDirectory[idx1][idx2] = rrmStream->readSint16LE(); + } + + // Read in the walk data + size = rrmStream->readUint16LE(); + Common::SeekableReadStream *walkStream = !_lzwMode ? rrmStream : + decompressLZ(*rrmStream, size); + + _walkData.resize(size); + walkStream->read(&_walkData[0], size); + + if (_lzwMode) + delete walkStream; + + // Read in the exits + int numExits = rrmStream->readByte(); + _exits.resize(numExits); + + for (int idx = 0; idx < numExits; ++idx) + _exits[idx].synchronize(*rrmStream); + + // Read in the entrance + _entrance.synchronize(*rrmStream); + + // Initialize sound list + int numSounds = rrmStream->readByte(); + _sounds.resize(numSounds); + + for (int idx = 0; idx < numSounds; ++idx) + _sounds[idx].synchronize(*rrmStream); + + // If sound is turned on, load the sounds into memory + if (sound._sfxEnabled) { + for (int idx = 0; idx < numSounds; ++idx) { + sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority); + _sounds[idx]._name = ""; + } + } + + // Read in palette + rrmStream->read(screen._cMap, PALETTE_SIZE); + for (int idx = 0; idx < PALETTE_SIZE; ++idx) + screen._cMap[idx] = VGA_COLOR_TRANS(screen._cMap[idx]); + + Common::copy(screen._cMap, screen._cMap + PALETTE_SIZE, screen._sMap); + + // Read in the background + Common::SeekableReadStream *bgStream = !_lzwMode ? rrmStream : + decompressLZ(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); + + bgStream->read(screen._backBuffer.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); + + if (_lzwMode) + delete bgStream; + + // Set the palette + screen._backBuffer2.blitFrom(screen._backBuffer); + screen.setPalette(screen._cMap); delete rrmStream; } + // Clear user interface area and draw controls + screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK); + screen._backBuffer.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); + screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); + + _changes = false; + checkSceneStatus(); + + if (!_vm->_justLoaded) { + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type == HIDDEN && _bgShapes[idx]._aType == TALK_EVERY) + _bgShapes[idx].toggleHidden(); + } + + // Check for TURNON objects + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type == HIDDEN && (_bgShapes[idx]._flags & 0x20)) + _bgShapes[idx].toggleHidden(); + } + + // Check for TURNOFF objects + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type != HIDDEN && (_bgShapes[idx]._flags & 0x40) && + _bgShapes[idx]._type != INVALID) + _bgShapes[idx].toggleHidden(); + } + } + + checkSceneFlags(false); + checkInventory(); + + // TODO +} + +/** + * Set objects to their current persistent state. This includes things such as + * opening or moving them + */ +void Scene::checkSceneStatus() { + if (_stats[_currentScene][8]) { + for (int idx = 0; idx < 8; ++idx) { + int val = _stats[_currentScene][idx]; + + for (int bit = 0; bit < 8; ++bit) { + uint objNumber = idx * 8 + bit; + if (objNumber < _bgShapes.size()) { + Object &obj = _bgShapes[objNumber]; + + if (val & 1) { + // No shape to erase, so flag as hidden + obj._type = HIDDEN; + } else if (obj._images == nullptr || obj._images->size() == 0) { + // No shape + obj._type = NO_SHAPE; + } else { + obj._type = ACTIVE_BG_SHAPE; + } + } else { + // Finished checks + return; + } + + val >>= 1; + } + } + } +} + +/** + * Check the scene's objects against the game flags. If false is passed, + * it means the scene has just been loaded. A value of true means that the scene + * is in use (ie. not just loaded) + */ +void Scene::checkSceneFlags(bool flag) { + int mode = mode ? HIDE_SHAPE : HIDDEN; + + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + // TODO: read_flags calls + } +} + +/** + * Checks scene objects against the player's inventory items. If there are any + * matching names, it means the given item has already been picked up, and should + * be hidden in the scene. + */ +void Scene::checkInventory() { + } } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 2280e169b7..ae4fcfdb45 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -32,6 +32,10 @@ namespace Sherlock { #define SCENES_COUNT 63 +#define MAX_ZONES 40 +#define INFO_LINE 140 +#define CONTROLS_Y 138 +#define CONTROLS_Y1 151 class SherlockEngine; @@ -54,6 +58,33 @@ struct BgfileheaderInfo { void synchronize(Common::SeekableReadStream &s); }; +struct Exit { + Common::Point _position; + Common::Point _size; + + int _scene; + int _allow; + Common::Point _people; + int _peopleDir; + + void synchronize(Common::SeekableReadStream &s); +}; + +struct SceneEntry { + Common::Point _startPosition; + int _startDir; + int _allow; + + void synchronize(Common::SeekableReadStream &s); +}; + +struct SceneSound { + Common::String _name; + int _priority; + + void synchronize(Common::SeekableReadStream &s); +}; + class Scene { private: SherlockEngine *_vm; @@ -61,15 +92,23 @@ private: void loadScene(); void loadScene(const Common::String &filename); + + void checkSceneStatus(); + + void checkSceneFlags(bool mode); + + void checkInventory(); public: + int _currentScene; + int _goToRoom; + bool _changes; bool _stats[SCENES_COUNT][9]; bool _savedStats[SCENES_COUNT][9]; - int _goToRoom; Common::Point _bigPos; Common::Point _overPos; int _oldCharPoint; ImageFile *_controls; - int _numExits; + ImageFile *_controlPanel; bool _windowOpen, _infoFlag; int _menuMode, _keyboardInput; int _oldKey, _help, _oldHelp; @@ -86,6 +125,11 @@ public: Common::Array<CAnim> _cAnim; Common::Array<byte> _sequenceBuffer; Common::Array<InvGraphicType> _inv; + int _walkDirectory[MAX_ZONES][MAX_ZONES]; + Common::Array<byte> _walkData; + Common::Array<Exit> _exits; + SceneEntry _entrance; + Common::Array<SceneSound> _sounds; public: Scene(SherlockEngine *vm); ~Scene(); diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 0ec5df9c4c..b322b96d6b 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -32,6 +32,8 @@ Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCR _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { _transitionSeed = 1; _fadeStyle = false; + Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0); + Common::fill(&_sMap[0], &_sMap[PALETTE_SIZE], 0); setFont(1); } diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 05fd80a8b7..2c5e585475 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -34,6 +34,7 @@ namespace Sherlock { #define PALETTE_SIZE 768 #define PALETTE_COUNT 256 #define VGA_COLOR_TRANS(x) ((x) * 255 / 63) +#define INFO_BLACK 1 class SherlockEngine; @@ -52,6 +53,8 @@ protected: public: Surface _backBuffer, _backBuffer2; bool _fadeStyle; + byte _cMap[PALETTE_SIZE]; + byte _sMap[PALETTE_SIZE]; public: Screen(SherlockEngine *vm); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index a963d0bfe5..115d9f0130 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -43,6 +43,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _useEpilogue2 = false; _hsavedPos = Common::Point(-1, -1); _hsavedFs = -1; + _justLoaded = false; } SherlockEngine::~SherlockEngine() { diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 210e24c320..c31416f91e 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -59,6 +59,7 @@ enum { #define SHERLOCK_SCREEN_WIDTH 320 #define SHERLOCK_SCREEN_HEIGHT 200 +#define SHERLOCK_SCENE_HEIGHT 138 struct SherlockGameDescription; @@ -91,6 +92,7 @@ public: bool _useEpilogue2; Common::Point _hsavedPos; int _hsavedFs; + bool _justLoaded; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index efc1965637..61c740ea3f 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -32,6 +32,10 @@ Sound::Sound(SherlockEngine *vm): _vm(vm) { _music = false; } +void Sound::loadSound(const Common::String &name, int priority) { + // TODO +} + void Sound::playSound(const Common::String &name, WaitType waitType) { // TODO } diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 442e908838..9d323833f1 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -46,6 +46,7 @@ public: public: Sound(SherlockEngine *vm); + void loadSound(const Common::String &name, int priority); void playSound(const Common::String &name, WaitType waitType = WAIT_RETURN_IMMEDIATELY); void cacheSound(const Common::String &name, int index); void playCachedSound(int index); |