aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/startrek/awaymission.cpp16
-rw-r--r--engines/startrek/filestream.cpp8
-rw-r--r--engines/startrek/filestream.h2
-rw-r--r--engines/startrek/graphics.cpp65
-rw-r--r--engines/startrek/graphics.h11
-rw-r--r--engines/startrek/menu.cpp8
-rw-r--r--engines/startrek/room.h8
-rw-r--r--engines/startrek/startrek.cpp145
-rw-r--r--engines/startrek/startrek.h21
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;