diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/startrek/awaymission.cpp | 16 | ||||
-rw-r--r-- | engines/startrek/filestream.cpp | 8 | ||||
-rw-r--r-- | engines/startrek/filestream.h | 2 | ||||
-rw-r--r-- | engines/startrek/graphics.cpp | 65 | ||||
-rw-r--r-- | engines/startrek/graphics.h | 11 | ||||
-rw-r--r-- | engines/startrek/menu.cpp | 8 | ||||
-rw-r--r-- | engines/startrek/room.h | 8 | ||||
-rw-r--r-- | engines/startrek/startrek.cpp | 145 | ||||
-rw-r--r-- | engines/startrek/startrek.h | 21 |
9 files changed, 249 insertions, 35 deletions
diff --git a/engines/startrek/awaymission.cpp b/engines/startrek/awaymission.cpp index c3fe9f732d..158d8c6ece 100644 --- a/engines/startrek/awaymission.cpp +++ b/engines/startrek/awaymission.cpp @@ -109,7 +109,12 @@ void StarTrekEngine::loadRoom(const Common::String &missionName, int roomIndex) int16 den = _room->getMaxY() - _room->getMinY() + 1; _playerActorScale = Fixed16(num) / den; - // TODO: RDF vars 1e/1f and 20/21; relates to BAN files? + int16 addr = _room->getBanDataStart(); + while (addr != _room->getBanDataEnd()) { + Common::String name((char *)&_room->_rdfData[addr]); + loadBanFile(name); + addr += strlen((char *)&_room->_rdfData[addr]) + 1; + } _actionQueue.clear(); } @@ -181,10 +186,13 @@ void StarTrekEngine::handleAwayMissionEvents() { case TREKEVENT_TICK: updateActorAnimations(); updateCrewmanGetupTimers(); + updateMouseBitmap(); - // doSomethingWithBanData1(); - _gfx->drawAllSprites(); - // doSomethingWithBanData2(); + renderBanBelowSprites(); + _gfx->drawAllSprites(false); + renderBanAboveSprites(); + _gfx->updateScreen(); + _sound->checkLoopMusic(); updateAwayMissionTimers(); _frameIndex++; diff --git a/engines/startrek/filestream.cpp b/engines/startrek/filestream.cpp index faae962ed5..e0916fc8e8 100644 --- a/engines/startrek/filestream.cpp +++ b/engines/startrek/filestream.cpp @@ -53,6 +53,14 @@ uint32 FileStream::readUint32() { return w; } +int16 FileStream::readSint16() { + return (int16)readUint16(); +} + +int32 FileStream::readSint32() { + return (int32)readUint32(); +} + // SeekableReadStream functions int32 FileStream::pos() const { diff --git a/engines/startrek/filestream.h b/engines/startrek/filestream.h index c5f5ef38cc..3b52b20ae6 100644 --- a/engines/startrek/filestream.h +++ b/engines/startrek/filestream.h @@ -46,6 +46,8 @@ public: byte readByte(); uint16 readUint16(); uint32 readUint32(); + int16 readSint16(); + int32 readSint32(); // SeekableReadStream functions int32 pos() const; diff --git a/engines/startrek/graphics.cpp b/engines/startrek/graphics.cpp index 6e8c97f902..43358f8c1c 100644 --- a/engines/startrek/graphics.cpp +++ b/engines/startrek/graphics.cpp @@ -109,6 +109,14 @@ byte *Graphics::getBackgroundPixels() { return _backgroundImage->pixels; } +byte *Graphics::lockScreenPixels() { + return (byte *)_vm->_system->lockScreen()->getPixels(); +} + +void Graphics::unlockScreenPixels() { + _vm->_system->unlockScreen(); +} + void Graphics::clearScreenAndPriBuffer() { Common::fill(_priData, _priData + sizeof(_priData), 0); @@ -571,28 +579,24 @@ void Graphics::drawAllSprites(bool updateScreen) { surface.free(); - if (updateScreen) { - // Check if there are any pending updates to the mouse. - if (_mouseBitmap != _mouseBitmapLastFrame) { - _mouseBitmapLastFrame = _mouseBitmap; - _vm->_system->setMouseCursor(_mouseBitmap->pixels, _mouseBitmap->width, _mouseBitmap->height, _mouseBitmap->xoffset, _mouseBitmap->yoffset, 0); - } - if (_mouseToBeShown) { - CursorMan.showMouse(true); - _mouseToBeShown = false; - } else if (_mouseToBeHidden) { - CursorMan.showMouse(false); - _mouseToBeHidden = false; - } + if (updateScreen) + this->updateScreen(); +} - if (_mouseWarpX != -1) { - _vm->_system->warpMouse(_mouseWarpX, _mouseWarpY); - _mouseWarpX = -1; - _mouseWarpY = -1; - } +void Graphics::drawAllSpritesInRect(const Common::Rect &rect) { + ::Graphics::Surface *surface = _vm->_system->lockScreen(); + + for (int i = 0; i < _numSprites; i++) { + Sprite *sprite = _sprites[i]; + if (!sprite->isOnScreen) + continue; - _vm->_system->updateScreen(); + Common::Rect intersect = rect.findIntersectingRect(sprite->drawRect); + if (!intersect.isEmpty()) + drawSprite(*sprite, surface, intersect); } + + _vm->_system->unlockScreen(); } void Graphics::forceDrawAllSprites(bool updateScreen) { @@ -601,6 +605,29 @@ void Graphics::forceDrawAllSprites(bool updateScreen) { drawAllSprites(updateScreen); } +void Graphics::updateScreen() { + // Check if there are any pending updates to the mouse. + if (_mouseBitmap != _mouseBitmapLastFrame) { + _mouseBitmapLastFrame = _mouseBitmap; + _vm->_system->setMouseCursor(_mouseBitmap->pixels, _mouseBitmap->width, _mouseBitmap->height, _mouseBitmap->xoffset, _mouseBitmap->yoffset, 0); + } + if (_mouseToBeShown) { + CursorMan.showMouse(true); + _mouseToBeShown = false; + } else if (_mouseToBeHidden) { + CursorMan.showMouse(false); + _mouseToBeHidden = false; + } + + if (_mouseWarpX != -1) { + _vm->_system->warpMouse(_mouseWarpX, _mouseWarpY); + _mouseWarpX = -1; + _mouseWarpY = -1; + } + + _vm->_system->updateScreen(); +} + Sprite *Graphics::getSpriteAt(int16 x, int16 y) { for (int i = _numSprites - 1; i >= 0; i--) { Sprite *sprite = _sprites[i]; diff --git a/engines/startrek/graphics.h b/engines/startrek/graphics.h index ecef5fc9ea..1a71aa29b3 100644 --- a/engines/startrek/graphics.h +++ b/engines/startrek/graphics.h @@ -61,6 +61,8 @@ public: void fillBackgroundRect(const Common::Rect &rect, byte color); byte *getBackgroundPixels(); + byte *lockScreenPixels(); + void unlockScreenPixels(); void clearScreenAndPriBuffer(); /** @@ -106,10 +108,19 @@ public: void drawSprite(const Sprite &sprite, ::Graphics::Surface *surface, const Common::Rect &rect); void drawAllSprites(bool updateScreen = true); /** + * This function should only be called after "drawAllSprites" (so that sprite rects + * are updated). + */ + void drawAllSpritesInRect(const Common::Rect &rect); + /** * Sets "bitmapChanged" to true on all sprites before calling drawAllSprites. */ void forceDrawAllSprites(bool updateScreen = true); /** + * Flushes the screen. Usually called by "drawAllSprites". + */ + void updateScreen(); + /** * Returns the sprite at the given position (ignores mouse). */ Sprite *getSpriteAt(int16 x, int16 y); diff --git a/engines/startrek/menu.cpp b/engines/startrek/menu.cpp index aa9c3ebb82..5fbc8d5070 100644 --- a/engines/startrek/menu.cpp +++ b/engines/startrek/menu.cpp @@ -631,10 +631,12 @@ int StarTrekEngine::handleMenuEvents(uint32 ticksUntilClickingEnabled, bool inTe } // Not added: updating mouse position (scummvm handles that) - // sub_10492(); // TODO updateActorAnimations(); - _gfx->drawAllSprites(); - // sub_10BE7(); // TODO + renderBanBelowSprites(); + _gfx->drawAllSprites(false); + renderBanAboveSprites(); + _gfx->updateScreen(); + _sound->checkLoopMusic(); if (_finishedPlayingSpeech != 0) { diff --git a/engines/startrek/room.h b/engines/startrek/room.h index da3788053f..6c623a6ce5 100644 --- a/engines/startrek/room.h +++ b/engines/startrek/room.h @@ -47,6 +47,8 @@ struct RoomAction { // Offsets of data in RDF files +const int RDF_BAN_DATA_START = 0x1e; +const int RDF_BAN_DATA_END = 0x20; const int RDF_WARP_ROOM_INDICES = 0x22; const int RDF_ROOM_ENTRY_POSITIONS = 0x2a; const int RDF_BEAM_IN_POSITIONS = 0xaa; @@ -76,6 +78,12 @@ public: Fixed8 getMaxScale() { return Fixed8::fromRaw(readRdfWord(0x0c)); } + int16 getBanDataStart() { + return readRdfWord(RDF_BAN_DATA_START); + } + int16 getBanDataEnd() { + return readRdfWord(RDF_BAN_DATA_END); + } /** * Check if a particular action is defined for this room. diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp index 79681a88df..4703bbebb4 100644 --- a/engines/startrek/startrek.cpp +++ b/engines/startrek/startrek.cpp @@ -59,6 +59,7 @@ StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gam DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics"); DebugMan.addDebugChannel(kDebugSavegame, "savegame", "Savegames"); DebugMan.addDebugChannel(kDebugSpace, "space", "Space and Pseudo-3D"); + DebugMan.addDebugChannel(kDebugGeneral, "general", "General"); _gfx = nullptr; _sound = nullptr; @@ -568,11 +569,10 @@ void StarTrekEngine::stopPlayingSpeech() { } void StarTrekEngine::initActors() { - for (int i = 0; i < NUM_ACTORS; i++) { + for (int i = 0; i < NUM_ACTORS; i++) _actorList[i] = Actor(); - } - for (int i = 0; i < NUM_ACTORS / 2; i++) - _actorBanFiles[i].reset(); + for (int i = 0; i < MAX_BAN_FILES; i++) + _banFiles[i].reset(); strcpy(_kirkActor->animationString, "kstnd"); strcpy(_spockActor->animationString, "sstnd"); @@ -604,6 +604,19 @@ int StarTrekEngine::loadActorAnim(int actorIndex, const Common::String &animName return actorIndex; } +void StarTrekEngine::loadBanFile(const Common::String &name) { + debugC(kDebugGeneral, 7, "Load BAN file: %s.ban", name.c_str()); + for (int i = 0; i < MAX_BAN_FILES; i++) { + if (!_banFiles[i]) { + _banFiles[i] = loadFile(name + ".ban"); + _banFileOffsets[i] = 0; + return; + } + } + + warning("Couldn't load .BAN file \"%s.ban\"", name.c_str()); +} + bool StarTrekEngine::actorWalkToPosition(int actorIndex, const Common::String &animFile, int16 srcX, int16 srcY, int16 destX, int16 destY) { debugC(6, "Obj %d: walk from (%d,%d) to (%d,%d)", actorIndex, srcX, srcY, destX, destY); @@ -773,6 +786,126 @@ void StarTrekEngine::updateActorAnimations() { } } +void StarTrekEngine::renderBanBelowSprites() { + if ((_frameIndex & 3) != 0) + return; + + byte *screenPixels = _gfx->lockScreenPixels(); + byte *bgPixels = _gfx->getBackgroundPixels(); + + for (int i = 0; i < MAX_BAN_FILES; i++) { + if (!_banFiles[i]) + continue; + + // TODO: video modes other than VGA + + _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET); + uint16 offset = _banFiles[i]->readUint16(); + + if (offset == 0xffff) { + _banFileOffsets[i] = 0; + _banFiles[i]->seek(0, SEEK_SET); + offset = _banFiles[i]->readSint16(); + } + + int16 size = _banFiles[i]->readSint16(); + if (size != 0) { + _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET); + renderBan(screenPixels, _banFiles[i]); + + _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET); + renderBan(bgPixels, _banFiles[i]); + //sub_10e51(_gfx->getBackgroundPixels(), _banFiles[i]); + } + + } + + _gfx->unlockScreenPixels(); +} + +void StarTrekEngine::renderBan(byte *destPixels, SharedPtr<FileStream> banFile) { + uint16 offset = banFile->readUint16(); + int32 size = banFile->readUint16(); + + byte *dest = destPixels + offset; + + // Skip 8 bytes (rectangle encompassing the area being drawn to) + banFile->readSint32(); + banFile->readSint32(); + + while (--size >= 0) { + assert(dest >= destPixels && dest < destPixels + SCREEN_WIDTH * SCREEN_HEIGHT); + int8 b = banFile->readByte(); + + if (b == -128) // Add value to destination (usually jumping to next row) + dest += banFile->readUint16(); + else if (b < 0) { // Repeated byte + byte c = banFile->readByte(); + if (c == 0) + dest += (-b) + 1; + else { + for (int j = 0; j < (-b) + 1; j++) + (*dest++) = c; + } + } else { // List of bytes + b++; + while (b-- != 0) { + byte c = banFile->readByte(); + if (c == 0) + dest++; + else + *(dest++) = c; + } + } + } +} + +void StarTrekEngine::renderBanAboveSprites() { + if ((_frameIndex & 3) != 0) + return; + + for (int i = 0; i < MAX_BAN_FILES; i++) { + if (!_banFiles[i]) + continue; + + _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET); + uint16 offset = _banFiles[i]->readUint16(); + + if (offset == 0xffff) { + _banFileOffsets[i] = 0; + _banFiles[i]->seek(0, SEEK_SET); + offset = _banFiles[i]->readSint16(); + } + + int16 size = _banFiles[i]->readSint16(); + if (size != 0) { + Common::Rect rect; + rect.left = _banFiles[i]->readSint16(); + rect.top = _banFiles[i]->readSint16(); + rect.right = _banFiles[i]->readSint16() + 1; + rect.bottom = _banFiles[i]->readSint16() + 1; + _gfx->drawAllSpritesInRect(rect); + + // Just read through the BAN data to get the end address, not doing anything + // with it. + while (--size >= 0) { + int8 b = _banFiles[i]->readByte(); + if (b == -128) + _banFiles[i]->readUint16(); + else if (b < 0) { + _banFiles[i]->readByte(); + } else { + b++; + while (b-- != 0) + _banFiles[i]->readByte(); + } + } + + _banFileOffsets[i] = _banFiles[i]->pos(); + } + } +} + void StarTrekEngine::removeActorFromScreen(int actorIndex) { Actor *actor = &_actorList[actorIndex]; @@ -796,8 +929,8 @@ void StarTrekEngine::actorFunc1() { } } - for (int i = 0; i < NUM_ACTORS / 2; i++) { - _actorBanFiles[i].reset(); + for (int i = 0; i < MAX_BAN_FILES; i++) { + _banFiles[i].reset(); } } diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h index 6e17375791..6f98db2b64 100644 --- a/engines/startrek/startrek.h +++ b/engines/startrek/startrek.h @@ -109,6 +109,8 @@ const int MAX_TEXTBOX_LINES = 12; const int MAX_BUFFERED_WALK_ACTIONS = 32; +const int MAX_BAN_FILES = 16; + enum StarTrekGameType { GType_ST25 = 1, @@ -123,7 +125,8 @@ enum kDebugLevels { kDebugSound = 1 << 0, kDebugGraphics = 1 << 1, kDebugSavegame = 1 << 2, - kDebugSpace = 2 << 3 + kDebugSpace = 1 << 3, + kDebugGeneral = 1 << 4 }; enum GameMode { @@ -342,12 +345,22 @@ public: * Set an actor's animation, position, and scale. */ int loadActorAnim(int actorIndex, const Common::String &animName, int16 x, int16 y, Fixed8 scale); + void loadBanFile(const Common::String &name); /** * Tries to make an actor walk to a position. * Returns true if successful in initiating the walk. */ bool actorWalkToPosition(int actorIndex, const Common::String &animFile, int16 srcX, int16 srcY, int16 destX, int16 destY); void updateActorAnimations(); + + /** + * ".BAN" files relate to drawing background animations, ie. flashing computer lights. + * "renderBanBelowSprites()" does the work of drawing it, while + * "renderBanAboveSprites()" redraws sprites above them if necessary. + */ + void renderBanBelowSprites(); + void renderBan(byte *pixelDest, SharedPtr<FileStream> file); + void renderBanAboveSprites(); void removeActorFromScreen(int actorIndex); void actorFunc1(); void drawActorToScreen(Actor *actor, const Common::String &animName, int16 x, int16 y, Fixed8 scale, bool addSprite); @@ -664,8 +677,10 @@ public: Actor *const _mccoyActor; Actor *const _redshirtActor; - SharedPtr<FileStream> _actorBanFiles[NUM_ACTORS / 2]; - uint16 _actorBanVar2[NUM_ACTORS / 2]; // TODO: initialize? + // ".BAN" files provide extra miscellaneous animations in the room, ie. flashing + // pixels on computer consoles, or fireflies in front of the screen. + SharedPtr<FileStream> _banFiles[MAX_BAN_FILES]; + uint16 _banFileOffsets[MAX_BAN_FILES]; Sprite _inventoryIconSprite; Sprite _itemIconSprite; |