aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Stewart2018-05-11 02:17:57 -0400
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commitd375429abef0109a483970975b053292efa4bd6e (patch)
tree448bd50bc330010834b3e1f655903bf1b2d7e93e
parentfde5f22f9783c557c74d0267d8118c1a0c6d498e (diff)
downloadscummvm-rg350-d375429abef0109a483970975b053292efa4bd6e.tar.gz
scummvm-rg350-d375429abef0109a483970975b053292efa4bd6e.tar.bz2
scummvm-rg350-d375429abef0109a483970975b053292efa4bd6e.zip
STARTREK: Objects and animations.
Testing them with the transporter room.
-rw-r--r--engines/startrek/filestream.h2
-rw-r--r--engines/startrek/font.cpp2
-rw-r--r--engines/startrek/graphics.cpp121
-rw-r--r--engines/startrek/graphics.h20
-rw-r--r--engines/startrek/module.mk1
-rw-r--r--engines/startrek/object.cpp27
-rw-r--r--engines/startrek/object.h83
-rw-r--r--engines/startrek/room.cpp2
-rw-r--r--engines/startrek/sound.cpp7
-rw-r--r--engines/startrek/sound.h5
-rw-r--r--engines/startrek/sprite.h12
-rw-r--r--engines/startrek/startrek.cpp517
-rw-r--r--engines/startrek/startrek.h61
-rw-r--r--engines/startrek/text.cpp8
14 files changed, 700 insertions, 168 deletions
diff --git a/engines/startrek/filestream.h b/engines/startrek/filestream.h
index 475bbcfeea..dcc806043c 100644
--- a/engines/startrek/filestream.h
+++ b/engines/startrek/filestream.h
@@ -39,7 +39,7 @@ private:
public:
// ReadStream functions
virtual bool eos() const;
- virtual uint32 read(void* dataPtr, uint32 dataSize);
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
// SeekableReadStream functions
virtual int32 pos() const;
diff --git a/engines/startrek/font.cpp b/engines/startrek/font.cpp
index db310425a0..8463841ece 100644
--- a/engines/startrek/font.cpp
+++ b/engines/startrek/font.cpp
@@ -31,7 +31,7 @@ static const byte CHARACTER_COUNT = 0x80;
static const byte CHARACTER_SIZE = 0x40;
Font::Font(StarTrekEngine *vm) : _vm(vm) {
- SharedPtr<Common::SeekableReadStream> fontStream = _vm->openFile("FONT.FNT");
+ SharedPtr<Common::SeekableReadStream> fontStream = _vm->loadFile("FONT.FNT");
_characters = new Character[CHARACTER_COUNT];
diff --git a/engines/startrek/graphics.cpp b/engines/startrek/graphics.cpp
index ced8d82edb..457313cd51 100644
--- a/engines/startrek/graphics.cpp
+++ b/engines/startrek/graphics.cpp
@@ -33,9 +33,7 @@ namespace StarTrek {
Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) {
_font = nullptr;
-
_egaData = nullptr;
- _priData = nullptr;
_lutData = nullptr;
_screenRect = Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT);
@@ -50,6 +48,9 @@ Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) {
_numSprites = 0;
_textDisplayMode = TEXTDISPLAY_WAIT;
+ _textboxVar2 = 0;
+ _textboxVar6 = 0;
+ _textboxHasMultipleChoices = false;
setMouseCursor(loadBitmap("pushbtn"));
CursorMan.showMouse(true);
@@ -57,58 +58,22 @@ Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) {
Graphics::~Graphics() {
delete[] _egaData;
- delete[] _priData;
delete[] _lutData;
delete _font;
}
-void Graphics::loadEGAData(const char *filename) {
- // Load EGA palette data
- if (!_egaMode)
- return;
-
- if (!_egaData)
- _egaData = new byte[256];
-
- SharedPtr<Common::SeekableReadStream> egaStream = _vm->openFile(filename);
- egaStream->read(_egaData, 256);
+void Graphics::setBackgroundImage(SharedPtr<Bitmap> bitmap) {
+ _backgroundImage = bitmap;
}
-void Graphics::drawBackgroundImage(const char *filename) {
- // Draw an stjr BGD image (palette built-in)
-
- SharedPtr<Common::SeekableReadStream> imageStream = _vm->openFile(filename);
- byte *palette = new byte[256 * 3];
- imageStream->read(palette, 256 * 3);
-
- // Expand color components
- for (uint16 i = 0; i < 256 * 3; i++)
- palette[i] <<= 2;
-
- uint16 xoffset = imageStream->readUint16LE();
- uint16 yoffset = imageStream->readUint16LE();
- uint16 width = imageStream->readUint16LE();
- uint16 height = imageStream->readUint16LE();
-
- byte *pixels = new byte[width * height];
- imageStream->read(pixels, width * height);
-
- _vm->_system->getPaletteManager()->setPalette(palette, 0, 256);
- _vm->_system->copyRectToScreen(pixels, width, xoffset, yoffset, width, height);
- _vm->_system->updateScreen();
-
- delete[] palette;
-}
-
-
void Graphics::loadPalette(const Common::String &paletteName) {
// Set the palette from a PAL file
Common::String palFile = paletteName + ".PAL";
Common::String lutFile = paletteName + ".LUT";
- SharedPtr<Common::SeekableReadStream> palStream = _vm->openFile(palFile.c_str());
+ SharedPtr<Common::SeekableReadStream> palStream = _vm->loadFile(palFile.c_str());
byte *palette = new byte[256 * 3];
palStream->read(palette, 256 * 3);
@@ -122,7 +87,7 @@ void Graphics::loadPalette(const Common::String &paletteName) {
delete[] palette;
// Load LUT file
- SharedPtr<Common::SeekableReadStream> lutStream = _vm->openFile(lutFile.c_str());
+ SharedPtr<Common::SeekableReadStream> lutStream = _vm->loadFile(lutFile.c_str());
delete[] _lutData;
_lutData = new byte[256];
@@ -130,15 +95,27 @@ void Graphics::loadPalette(const Common::String &paletteName) {
}
void Graphics::loadPri(const char *priFile) {
- SharedPtr<Common::SeekableReadStream> priStream = _vm->openFile(priFile);
-
- delete[] _priData;
- _priData = new byte[SCREEN_WIDTH*SCREEN_HEIGHT / 2];
+ SharedPtr<Common::SeekableReadStream> priStream = _vm->loadFile(priFile);
priStream->read(_priData, SCREEN_WIDTH*SCREEN_HEIGHT / 2);
}
+void Graphics::clearPri() {
+ memset(_priData, 0, sizeof(_priData));
+}
+
+byte Graphics::getPriValue(int x, int y) {
+ assert(_screenRect.contains(x, y));
+
+ int priOffset = y * SCREEN_WIDTH + x;
+ byte b = _priData[priOffset / 2];
+ if ((priOffset % 2) == 1)
+ return b & 0xf;
+ else
+ return b >> 4;
+}
+
SharedPtr<Bitmap> Graphics::loadBitmap(Common::String basename) {
- return SharedPtr<Bitmap>(new Bitmap(_vm->openFile(basename + ".BMP")));
+ return SharedPtr<Bitmap>(new Bitmap(_vm->loadFile(basename + ".BMP")));
}
Common::Point Graphics::getMousePos() {
@@ -150,11 +127,6 @@ void Graphics::setMouseCursor(SharedPtr<Bitmap> bitmap) {
_vm->_system->setMouseCursor(bitmap->pixels, bitmap->width, bitmap->height, bitmap->xoffset, bitmap->yoffset, 0);
}
-void Graphics::redrawScreen() {
- _vm->_system->copyRectToScreen(_backgroundImage->pixels, SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
- drawAllSprites();
-}
-
void Graphics::drawSprite(const Sprite &sprite) {
int left = sprite.drawX;
int top = sprite.drawY;
@@ -448,17 +420,50 @@ void Graphics::delSprite(Sprite *sprite) {
}
-void Graphics::drawBitmapToScreen(Bitmap *bitmap) {
+void Graphics::drawDirectToScreen(SharedPtr<Bitmap> bitmap) {
int xoffset = bitmap->xoffset;
int yoffset = bitmap->yoffset;
- if (xoffset >= SCREEN_WIDTH)
- xoffset = 0;
- if (yoffset >= SCREEN_HEIGHT)
- yoffset = 0;
_vm->_system->copyRectToScreen(bitmap->pixels, bitmap->width, xoffset, yoffset, bitmap->width, bitmap->height);
- _vm->_system->updateScreen();
}
+void Graphics::loadEGAData(const char *filename) {
+ // Load EGA palette data
+ if (!_egaMode)
+ return;
+
+ if (!_egaData)
+ _egaData = new byte[256];
+
+ SharedPtr<Common::SeekableReadStream> egaStream = _vm->loadFile(filename);
+ egaStream->read(_egaData, 256);
+}
+
+void Graphics::drawBackgroundImage(const char *filename) {
+ // Draw an stjr BGD image (palette built-in)
+
+ SharedPtr<Common::SeekableReadStream> imageStream = _vm->loadFile(filename);
+ byte *palette = new byte[256 * 3];
+ imageStream->read(palette, 256 * 3);
+
+ // Expand color components
+ for (uint16 i = 0; i < 256 * 3; i++)
+ palette[i] <<= 2;
+
+ uint16 xoffset = imageStream->readUint16LE();
+ uint16 yoffset = imageStream->readUint16LE();
+ uint16 width = imageStream->readUint16LE();
+ uint16 height = imageStream->readUint16LE();
+
+ byte *pixels = new byte[width * height];
+ imageStream->read(pixels, width * height);
+
+ _vm->_system->getPaletteManager()->setPalette(palette, 0, 256);
+ _vm->_system->copyRectToScreen(pixels, width, xoffset, yoffset, width, height);
+ _vm->_system->updateScreen();
+
+ delete[] palette;
+}
+
}
diff --git a/engines/startrek/graphics.h b/engines/startrek/graphics.h
index 277c63615c..758f327d6b 100644
--- a/engines/startrek/graphics.h
+++ b/engines/startrek/graphics.h
@@ -70,18 +70,17 @@ public:
Graphics(StarTrekEngine *vm);
~Graphics();
- void loadEGAData(const char *egaFile);
- void drawBackgroundImage(const char *filename);
-
+ void setBackgroundImage(SharedPtr<Bitmap> bitmap);
void loadPalette(const String &paletteFile);
void loadPri(const char *priFile);
+ void clearPri();
+ byte getPriValue(int x, int y);
SharedPtr<Bitmap> loadBitmap(String basename);
Common::Point getMousePos();
void setMouseCursor(SharedPtr<Bitmap> bitmap);
- void redrawScreen();
void drawSprite(const Sprite &sprite);
void drawSprite(const Sprite &sprite, const Common::Rect &rect);
void drawAllSprites();
@@ -89,18 +88,19 @@ public:
void addSprite(Sprite *sprite);
void delSprite(Sprite *sprite);
+
+ void drawDirectToScreen(SharedPtr<Bitmap> bitmap);
+ void loadEGAData(const char *egaFile);
+ void drawBackgroundImage(const char *filename);
private:
- void drawBitmapToScreen(Bitmap *bitmap);
-
-
StarTrekEngine *_vm;
Font *_font;
bool _egaMode;
byte *_egaData;
- byte *_priData;
byte *_lutData;
+ byte _priData[SCREEN_WIDTH*SCREEN_HEIGHT / 2];
Common::Rect _screenRect;
SharedPtr<Bitmap> _backgroundImage;
@@ -156,11 +156,13 @@ public:
private:
int16 _textDisplayMode;
+
+public:
uint32 _textboxVar2;
- uint32 _textboxVar3;
uint16 _textboxVar6;
bool _textboxHasMultipleChoices;
+private:
SharedPtr<Menu> _activeMenu;
// Saved value of StarTrekEngine::_keyboardControlsMouse when menus are up
diff --git a/engines/startrek/module.mk b/engines/startrek/module.mk
index 9114de4632..3b93fbc439 100644
--- a/engines/startrek/module.mk
+++ b/engines/startrek/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS = \
font.o \
lzss.o \
graphics.o \
+ object.o \
room.o \
sound.o \
sprite.o \
diff --git a/engines/startrek/object.cpp b/engines/startrek/object.cpp
new file mode 100644
index 0000000000..aafa138ffe
--- /dev/null
+++ b/engines/startrek/object.cpp
@@ -0,0 +1,27 @@
+/* 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 "object.h"
+
+namespace StarTrek {
+
+}
diff --git a/engines/startrek/object.h b/engines/startrek/object.h
new file mode 100644
index 0000000000..41bf1f96c2
--- /dev/null
+++ b/engines/startrek/object.h
@@ -0,0 +1,83 @@
+/* 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.
+ *
+ */
+
+#ifndef STARTREK_OBJECT_H
+#define STARTREK_OBJECT_H
+
+#include "startrek/sprite.h"
+
+#include "common/scummsys.h"
+
+namespace StarTrek {
+
+class StarTrekEngine;
+class FileStream;
+
+
+struct Object {
+ uint16 spriteDrawn;
+ char animationString3[16];
+ uint16 animType;
+ Sprite sprite;
+ char animationString4[10];
+ uint16 scale;
+ SharedPtr<FileStream> animFile;
+ uint16 numAnimFrames;
+ uint16 animFrame;
+ uint32 frameToStartNextAnim;
+ uint16 field5e;
+ uint16 field60;
+ uint16 field62;
+ uint16 field64;
+ uint16 field66;
+ char animationString2[8];
+ uint16 field70;
+ uint16 field72;
+ uint16 field74;
+ uint16 field76;
+ uint16 iwSrcPosition;
+ uint16 iwDestPosition;
+ uint16 field7c;
+ uint16 field7e;
+ uint16 field80;
+ uint16 field82;
+ uint16 field84;
+ uint16 field86;
+ uint16 field88;
+ uint16 field8a;
+ uint16 field8c;
+ uint16 field8e;
+ uint16 field90;
+ uint16 field92;
+ uint16 field94;
+ uint16 field96;
+ char animationString[9];
+ uint8 fielda1;
+ uint16 fielda2;
+ uint16 fielda4;
+ uint16 fielda6;
+};
+
+}
+
+#endif
+
diff --git a/engines/startrek/room.cpp b/engines/startrek/room.cpp
index 3516aaa437..a68737454f 100644
--- a/engines/startrek/room.cpp
+++ b/engines/startrek/room.cpp
@@ -31,7 +31,7 @@
namespace StarTrek {
Room::Room(StarTrekEngine *vm, Common::String name) : _vm(vm) {
- SharedPtr<FileStream> rdfFile = _vm->openFile(name + ".RDF");
+ SharedPtr<FileStream> rdfFile = _vm->loadFile(name + ".RDF");
int size = rdfFile->size();
_rdfData = new byte[size];
diff --git a/engines/startrek/sound.cpp b/engines/startrek/sound.cpp
index 2871a88613..105b3a0b7a 100644
--- a/engines/startrek/sound.cpp
+++ b/engines/startrek/sound.cpp
@@ -149,6 +149,9 @@ void Sound::playMidiMusicTracks(int startTrack, int loopTrack) {
playMidiTrackInSlot(0, startTrack);
}
+/**
+ * TODO: original game had some caching of loaded voc files.
+ */
void Sound::playVoc(const Common::String &baseSoundName) {
/*
if (_vm->getPlatform() == Common::kPlatformAmiga)
@@ -169,7 +172,7 @@ void Sound::playVoc(const Common::String &baseSoundName) {
sub_2aaa3();
*/
- for (int i=0; i<MAX_SFX_PLAYING; i++) {
+ for (int i = 0; i < MAX_SFX_PLAYING; i++) {
if (_vm->_system->getMixer()->isSoundHandleActive(_sfxHandles[i]))
continue;
@@ -304,7 +307,7 @@ void Sound::loadPCMusicFile(const Common::String &baseSoundName) {
}
debugC(5, kDebugSound, "Loading midi \'%s\'\n", soundName.c_str());
- SharedPtr<Common::SeekableReadStream> soundStream = _vm->openFile(soundName.c_str());
+ SharedPtr<Common::SeekableReadStream> soundStream = _vm->loadFile(soundName.c_str());
if (loadedSoundData != nullptr)
delete[] loadedSoundData;
diff --git a/engines/startrek/sound.h b/engines/startrek/sound.h
index 2caa1d0010..6ce4e94a7c 100644
--- a/engines/startrek/sound.h
+++ b/engines/startrek/sound.h
@@ -82,11 +82,14 @@ private:
uint32 _midiDevice;
// VOC-related variables
- Common::String _loopingAudioName;
Audio::SoundHandle _sfxHandles[MAX_SFX_PLAYING];
Audio::SoundHandle _speechHandle;
bool _playingSpeech;
+public:
+ Common::String _loopingAudioName;
+
+private:
// Driver callback
static void midiDriverCallback(void *data);
};
diff --git a/engines/startrek/sprite.h b/engines/startrek/sprite.h
index 1e75cc416e..844fb80c35 100644
--- a/engines/startrek/sprite.h
+++ b/engines/startrek/sprite.h
@@ -63,18 +63,6 @@ struct Sprite {
Common::Rect getRect();
};
-
-class SpriteList {
-public:
- SpriteList(int n) { sprites = new Sprite[n]; }
- ~SpriteList() { delete[] sprites; }
-
- Sprite &operator[](int i) const { return sprites[i]; }
-
-private:
- Sprite *sprites;
-};
-
}
#endif
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index 40fa8d76da..8b05a5a3d2 100644
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -39,14 +39,24 @@
namespace StarTrek {
-StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gamedesc) : Engine(syst), _gameDescription(gamedesc) {
+StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gamedesc) :
+ Engine(syst),
+ _gameDescription(gamedesc),
+ _kirkObject(&_objectList[0]),
+ _spockObject(&_objectList[1]),
+ _mccoyObject(&_objectList[2]),
+ _redshirtObject(&_objectList[3]) {
+
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound");
+ DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics");
_gfx = nullptr;
_sound = nullptr;
_macResFork = nullptr;
_room = nullptr;
+ _redshirtDead = false;
+
_clockTicks = 0;
_musicEnabled = true;
@@ -82,86 +92,190 @@ Common::Error StarTrekEngine::run() {
}
initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT);
-
initializeEventsAndMouse();
-
-// Test graphics/music:
-
-// Music Status:
-// DOS Full: Adlib and MT-32 Sounds supported
-// DOS Demo: Adlib and MT-32 Sounds supported
-// Amiga: Sound effects supported
-// Macintosh: MIDI and sound effects playable, format not handled.
-
-// Graphics Status:
-// DOS/Amiga/Macintosh/Demo Graphics: 100%
-// Judgment Rites Backgrounds supported too
-// EGA not supported
+
+ _frameIndex = 0;
+
+ _gameMode = -1;
+ _lastGameMode = -1;
+
+ runGameMode(GAMEMODE_BEAMDOWN);
+ return Common::kNoError;
+
+
#if 1
_room = new Room(this, "DEMON0");
- if (getGameType() == GType_ST25) {
- _gfx->loadPalette("PALETTE");
- _gfx->loadPri("DEMON0.PRI");
- _gfx->redrawScreen();
-
- _sound->loadMusicFile("GROUND");
- } else {
- _gfx->drawBackgroundImage("BRIDGE.BGD");
- }
+ _gfx->loadPalette("PALETTE");
+ _gfx->loadPri("DEMON0.PRI");
- // Sprite tests
-
- // Draw mode 0
- Sprite *spr = new Sprite;
- _gfx->addSprite(spr);
- spr->bitmap = _gfx->loadBitmap("MWALKE00");
- spr->drawPriority = 1;
- spr->pos.x = 150;
- spr->pos.y = 100;
- spr->drawMode = 0;
-
- // Draw mode 2 (translucent background)
- spr = new Sprite;
- _gfx->addSprite(spr);
- spr->bitmap = _gfx->loadBitmap("KWALKS00");
- spr->drawPriority = 1;
- spr->pos.x = 230;
- spr->pos.y = 100;
- spr->drawMode = 2;
-
- /*
- // Draw mode 3 (text)
- spr = new Sprite;
- _gfx->addSprite(spr);
- spr->bitmap = SharedPtr<Bitmap>(new TextBitmap(8*8,8*8));
- for (int i=0;i<8*8;i++)
- spr->bitmap->pixels[i] = 0x40+i;
- spr->pos.x = 8*10;
- spr->pos.y = 50;
- spr->textColor = 0xb3;
- spr->drawMode = 3;
-
- // initTextSprite function
- spr = new Sprite;
- int x=0,y=0;
- _gfx->initTextSprite(&x, &y, 0xb3, 3, false, spr);
- spr->pos.y = 150;
- */
+ _sound->loadMusicFile("GROUND");
while (true) {
_gfx->showOptionsMenu(0, 0);
}
- _gfx->showText(&Graphics::readTextFromRdf, 0x2220, 150, 160, 0xb3, 0, 10, 0);
while (!shouldQuit()) {
pollSystemEvents();
}
+
+ return Common::kNoError;
#endif
+}
+
+Common::Error StarTrekEngine::runGameMode(int mode) {
+ _gameMode = mode;
+
+ _sound->stopAllVocSounds();
+ if (!_sound->_loopingAudioName.empty())
+ _sound->playVoc(_sound->_loopingAudioName);
+
+ if (_gameMode == GAMEMODE_START)
+ _gameMode = GAMEMODE_BRIDGE;
+
+ while (true) {
+ if (_gameMode != _lastGameMode) {
+ // Cleanup previous game mode
+ switch (_lastGameMode) {
+ case GAMEMODE_BRIDGE:
+ //cleanupBridgeMode();
+ break;
+
+ case GAMEMODE_AWAYMISSION:
+ //cleanupAwayMissionMode();
+ break;
+
+ case GAMEMODE_BEAMDOWN:
+ case GAMEMODE_BEAMUP:
+ break;
+ }
+
+ _lastGameMode = _gameMode;
+
+ // Load next game mode
+ switch (_gameMode) {
+ case GAMEMODE_BRIDGE:
+ _sound->loadMusicFile("bridge");
+ //initBridge();
+ break;
+
+ case GAMEMODE_AWAYMISSION:
+ //initAwayMission();
+ break;
+
+ case GAMEMODE_BEAMDOWN:
+ _redshirtDead = false;
+ _sound->loadMusicFile("ground");
+ runTransportSequence("teled");
+ _gameMode = GAMEMODE_AWAYMISSION;
+ continue; // Back to start of loop
+
+ case GAMEMODE_BEAMUP:
+ runTransportSequence("teleb");
+ _gameMode = GAMEMODE_BRIDGE;
+ //sub_15c61();
+ _sound->stopAllVocSounds();
+ _sound->playVoc("bridloop");
+ continue; // Back to start of loop
+ }
+ }
+
+ // Run current game mode
+ switch (_gameMode) {
+ case GAMEMODE_BRIDGE:
+ //runBridge();
+ break;
+
+ case GAMEMODE_AWAYMISSION:
+ //runAwayMission();
+ break;
+
+ case GAMEMODE_BEAMDOWN:
+ case GAMEMODE_BEAMUP:
+ error("Can't be here.");
+ break;
+ }
+ }
return Common::kNoError;
}
+void StarTrekEngine::runTransportSequence(const Common::String &name) {
+ const uint16 crewmanTransportPositions[][2] = {
+ { 0x8e, 0x7c },
+ { 0xbe, 0x7c },
+ { 0x7e, 0x72 },
+ { 0xaa, 0x72 }
+ };
+
+ _sound->stopAllVocSounds();
+ // sub_1e70d();
+ objectFunc1();
+ initObjects();
+
+ SharedPtr<Bitmap> bgImage = _gfx->loadBitmap("transprt");
+ _gfx->setBackgroundImage(bgImage);
+ _gfx->clearPri();
+ _gfx->loadPalette("palette");
+ _gfx->drawDirectToScreen(bgImage);
+ _system->updateScreen();
+
+ for (int i = 0; i < (_redshirtDead ? 3 : 4); i++) {
+ Common::String filename = getCrewmanAnimFilename(i, name);
+ int x = crewmanTransportPositions[i][0];
+ int y = crewmanTransportPositions[i][1];
+ loadAnimationForObject(i, filename, x, y, 256);
+ _objectList[i].animationString[0] = '\0';
+ }
+
+ if (_missionToLoad.equalsIgnoreCase("feather") && name[4] == 'b') {
+ loadAnimationForObject(9, "qteleb", 0x61, 0x79, 0x100);
+ }
+ else if (_missionToLoad.equalsIgnoreCase("trial")) {
+ if (name[4] == 'd') {
+ loadAnimationForObject(9, "qteled", 0x61, 0x79, 0x100);
+ }
+ /* TODO
+ else if (word_51156 >= 3) {
+ loadAnimationForObject(9, "qteleb", 0x61, 0x79, 0x100);
+ }
+ */
+ }
+
+ loadAnimationForObject(8, "transc", 0, 0, 0x100);
+
+ // TODO: redraw mouse and sprite_52c4e?
+
+ _gfx->drawAllSprites();
+ // sub_1e6ab();
+
+ playSoundEffectIndex(0x0a);
+
+ if (name.equalsIgnoreCase("teled"))
+ playSoundEffectIndex(0x08);
+ else
+ playSoundEffectIndex(0x09);
+
+ while (_objectList[0].field62 == 0) {
+ TrekEvent event;
+ if (popNextEvent(&event)) {
+ if (event.type == TREKEVENT_TICK) {
+ // TODO: redraw sprite_52c4e?
+ _frameIndex++;
+ updateObjectAnimations();
+ _gfx->drawAllSprites();
+ }
+ }
+ }
+
+ // TODO: redraw sprite_52c4e?
+
+ _gfx->drawAllSprites();
+ // sub_1e70d();
+ objectFunc1();
+ initObjects();
+}
+
Room *StarTrekEngine::getRoom() {
return _room;
}
@@ -191,13 +305,19 @@ void StarTrekEngine::pollSystemEvents() {
break;
}
}
- _gfx->drawAllSprites();
+
+ // FIXME: get the actual duration of a tick right
+ _clockTicks++;
+ TrekEvent tickEvent;
+ tickEvent.type = TREKEVENT_TICK;
+ tickEvent.tick = _clockTicks;
+ addEventToQueue(tickEvent);
_system->delayMillis(1000/60);
}
void StarTrekEngine::playSoundEffectIndex(int index) {
- switch(index) {
+ switch (index) {
case 0x04:
_sound->playVoc("tricorde");
break;
@@ -256,14 +376,262 @@ void StarTrekEngine::stopPlayingSpeech() {
_sound->stopPlayingSpeech();
}
+void StarTrekEngine::initObjects() {
+ for (int i = 0; i < MAX_OBJECTS; i++) {
+ _objectList[i] = Object();
+ }
+ for (int i = 0; i < MAX_OBJECTS / 2; i++)
+ _objectBanFiles[i].reset();
+
+ strcpy(_kirkObject->animationString, "kstnd");
+ strcpy(_spockObject->animationString, "sstnd");
+ strcpy(_mccoyObject->animationString, "mstnd");
+ strcpy(_redshirtObject->animationString, "rstnd");
+}
+
+int StarTrekEngine::loadAnimationForObject(int objectIndex, const Common::String &animName, uint16 x, uint16 y, uint16 arg8) {
+ debugC(6, kDebugGraphics, "Load animation '%s' on object %d", animName.c_str(), objectIndex);
+
+ Object *object;
+
+ if (objectIndex == -1) {
+ // TODO
+ }
+ else
+ object = &_objectList[objectIndex];
+
+ if (object->spriteDrawn) {
+ releaseAnim(object);
+ drawObjectToScreen(object, animName, x, y, arg8, false);
+ }
+ else {
+ drawObjectToScreen(object, animName, x, y, arg8, true);
+ }
+
+ object->field64 = 0;
+ object->field66 = 0;
+
+ return objectIndex;
+}
+
+void StarTrekEngine::updateObjectAnimations() {
+ for (int i = 0; i < MAX_OBJECTS; i++) {
+ Object *object = &_objectList[i];
+ if (!object->spriteDrawn)
+ continue;
+
+ switch (object->animType) {
+ case 0:
+ case 2:
+ if (object->frameToStartNextAnim >= _frameIndex) {
+ int nextAnimIndex = 0; // TODO: "chooseNextAnimFrame" function
+ object->animFile->seek(18 + nextAnimIndex + object->animFrame * 22, SEEK_SET);
+ byte nextAnimFrame = object->animFile->readByte();
+
+ debugC(7, kDebugGraphics, "Object %d animation frame %d", i, nextAnimFrame);
+
+ if (object->animFrame != nextAnimFrame) {
+ if (nextAnimFrame == object->numAnimFrames - 1) {
+ object->field62++;
+ if (object->field64 != 0) {
+ // sub_20099(10, object->field66, 0, 0);
+ }
+ }
+ }
+
+ object->animFrame = nextAnimFrame;
+ if (object->animFrame >= object->numAnimFrames) {
+ if (object->animationString[0] == '\0')
+ removeObjectFromScreen(i);
+ /*
+ else // TODO
+ initStandAnim(i);
+ */
+ }
+ else {
+ Sprite *sprite = &object->sprite;
+
+ object->animFile->seek(object->animFrame * 22, SEEK_SET);
+ char animFrameFilename[16];
+ object->animFile->read(animFrameFilename, 16);
+ sprite->setBitmap(loadAnimationFrame(animFrameFilename, object->scale));
+
+ memset(object->animationString4, 0, 16);
+ strncpy(object->animationString4, animFrameFilename, 15);
+
+ object->animFile->seek(10, SEEK_SET);
+ uint16 xOffset = object->animFile->readUint16();
+ uint16 yOffset = object->animFile->readUint16();
+ uint16 basePriority = object->animFile->readUint16();
+
+ sprite->pos.x = xOffset + object->field5e;
+ sprite->pos.y = yOffset + object->field60;
+ sprite->drawPriority = _gfx->getPriValue(0, yOffset + object->field60) + basePriority;
+ sprite->bitmapChanged = true;
+
+ object->frameToStartNextAnim = object->animFile->readUint16() + _frameIndex;
+ }
+ }
+ break;
+ case 1: // TODO
+ warning("Unimplemented anim type %d", object->animType);
+ break;
+ default:
+ error("Invalid anim type.");
+ break;
+ }
+ }
+}
+
+void StarTrekEngine::removeObjectFromScreen(int objectIndex) {
+ Object *object = &_objectList[objectIndex];
+
+ if (object->spriteDrawn != 1)
+ return;
+
+ debugC(6, kDebugGraphics, "Stop drawing object %d", objectIndex);
+
+ Sprite *sprite = &object->sprite;
+ sprite->field16 = true;
+ sprite->bitmapChanged = true;
+ _gfx->drawAllSprites();
+ _gfx->delSprite(sprite);
+ releaseAnim(object);
+}
+
+void StarTrekEngine::objectFunc1() {
+ for (int i = 0; i < MAX_OBJECTS; i++) {
+ if (_objectList[i].spriteDrawn == 1) {
+ removeObjectFromScreen(i);
+ }
+ }
+
+ for (int i = 0; i < MAX_OBJECTS / 2; i++) {
+ _objectBanFiles[i].reset();
+ }
+}
+
+void StarTrekEngine::drawObjectToScreen(Object *object, const Common::String &_animName, uint16 x, uint16 y, uint16 arg8, bool addSprite) {
+ Common::String animFilename = _animName;
+ if (_animName.hasPrefixIgnoreCase("stnd") /* && word_45d20 == -1 */) // TODO
+ animFilename += 'j';
+ memcpy(object->animationString3, _animName.c_str(), sizeof(object->animationString3));
+
+ object->animType = 2;
+ object->animFile = loadFile(animFilename + ".anm");
+ object->numAnimFrames = object->animFile->size() / 22;
+ object->animFrame = 0;
+ object->field5e = x;
+ object->field60 = y;
+ object->field62 = 0;
+ object->scale = arg8;
+
+ object->animFile->seek(16, SEEK_SET);
+ object->frameToStartNextAnim = object->animFile->readUint16() + _frameIndex;
+
+ char firstFrameFilename[10];
+ object->animFile->seek(0, SEEK_SET);
+ object->animFile->read(firstFrameFilename, 10);
+
+ Sprite *sprite = &object->sprite;
+ if (addSprite)
+ _gfx->addSprite(sprite);
+
+ sprite->setBitmap(loadAnimationFrame(firstFrameFilename, arg8));
+ memset(object->animationString4, 0, sizeof(char) * 10);
+ strncpy(object->animationString4, firstFrameFilename, sizeof(char) * 9);
+
+ object->scale = arg8;
+
+ object->animFile->seek(10, SEEK_SET);
+ uint16 xOffset = object->animFile->readUint16();
+ uint16 yOffset = object->animFile->readUint16();
+ uint16 basePriority = object->animFile->readUint16();
+
+ sprite->pos.x = xOffset + object->field5e;
+ sprite->pos.y = yOffset + object->field60;
+ sprite->drawPriority = _gfx->getPriValue(0, yOffset + object->field60) + basePriority;
+ sprite->bitmapChanged = true;
+
+ object->spriteDrawn = 1;
+}
+
+void StarTrekEngine::releaseAnim(Object *object) {
+ switch (object->animType) {
+ case 0:
+ case 2:
+ object->sprite.bitmap.reset();
+ object->animFile.reset();
+ break;
+ case 1: // TODO
+ warning("Unimplemented anim type %d", object->animType);
+ break;
+ default:
+ error("Invalid anim type.");
+ break;
+ }
+
+ object->spriteDrawn = 0;
+}
+
+SharedPtr<Bitmap> StarTrekEngine::loadAnimationFrame(const Common::String &filename, uint16 arg2) {
+ SharedPtr<Bitmap> bitmapToReturn;
+
+ char basename[5];
+ strncpy(basename, filename.c_str()+1, 4);
+ basename[4] = '\0';
+
+ char c = filename[0];
+ if ((strcmp(basename, "stnd") == 0 || strcmp(basename, "tele") == 0)
+ && (c == 'm' || c == 's' || c == 'k' || c == 'r')) {
+ if (c == 'm') {
+ bitmapToReturn = _gfx->loadBitmap(filename);
+ }
+ else {
+ // bitmapToReturn = _gfx->loadBitmap(filename + ".$bm"); // FIXME: should be this?
+ if (bitmapToReturn == nullptr) {
+ Common::String newFilename = filename;
+ newFilename.setChar('m', 0); // FIXME: original writes directly to argument; does that affect anything?
+ bitmapToReturn = _gfx->loadBitmap(newFilename);
+ }
+ }
+ }
+ else {
+ // TODO: when loading a bitmap, it passes a different argument than is standard to
+ // the "file loading with cache" function...
+ bitmapToReturn = _gfx->loadBitmap(filename);
+ }
+
+ if (arg2 != 256) {
+ // TODO
+ // bitmapToReturn = scaleBitmap(bitmapToReturn, arg2);
+ }
+
+ return bitmapToReturn;
+}
+
+Common::String StarTrekEngine::getCrewmanAnimFilename(int objectIndex, const Common::String &basename) {
+ const char *crewmanChars = "ksmr";
+ assert(objectIndex >= 0 && objectIndex < 4);
+ return crewmanChars[objectIndex] + basename;
+}
+
void StarTrekEngine::updateClockTicks() {
// TODO (based on DOS interrupt 1A, AH=0; read system clock counter)
_clockTicks = 0;
}
-SharedPtr<FileStream> StarTrekEngine::openFile(Common::String filename, int fileIndex) {
+/**
+ * TODO:
+ * - Should return nullptr on failure to open a file?
+ * - This is supposed to cache results, return same FileStream on multiple accesses.
+ * - This is supposed to read from a "patches" folder which overrides files in the
+ * packed blob.
+ */
+SharedPtr<FileStream> StarTrekEngine::loadFile(Common::String filename, int fileIndex) {
filename.toUppercase();
+
Common::String basename, extension;
bool bigEndian = getPlatform() == Common::kPlatformAmiga;
@@ -278,11 +646,18 @@ SharedPtr<FileStream> StarTrekEngine::openFile(Common::String filename, int file
}
}
+ // FIXME: don't know if this is right, or if it goes here
+ while (!basename.empty() && basename.lastChar() == ' ') {
+ basename.erase(basename.size() - 1, 1);
+ }
+
+ filename = basename + '.' + extension;
+
// The Judgment Rites demo has its files not in the standard archive
if (getGameType() == GType_STJR && (getFeatures() & GF_DEMO)) {
Common::File *file = new Common::File();
if (!file->open(filename.c_str()))
- error ("Could not find file \'%s\'", filename.c_str());
+ error("Could not find file \'%s\'", filename.c_str());
return SharedPtr<FileStream>(new FileStream(file, bigEndian));
}
@@ -291,7 +666,7 @@ SharedPtr<FileStream> StarTrekEngine::openFile(Common::String filename, int file
if (getPlatform() == Common::kPlatformAmiga) {
indexFile = SearchMan.createReadStreamForMember("data000.dir");
if (!indexFile)
- error ("Could not open data000.dir");
+ error("Could not open data000.dir");
} else if (getPlatform() == Common::kPlatformMacintosh) {
indexFile = _macResFork->getResource("Directory");
if (!indexFile)
@@ -299,7 +674,7 @@ SharedPtr<FileStream> StarTrekEngine::openFile(Common::String filename, int file
} else {
indexFile = SearchMan.createReadStreamForMember("data.dir");
if (!indexFile)
- error ("Could not open data.dir");
+ error("Could not open data.dir");
}
uint32 indexOffset = 0;
@@ -353,9 +728,9 @@ SharedPtr<FileStream> StarTrekEngine::openFile(Common::String filename, int file
if ((basename.lastChar() >= '1' && basename.lastChar() <= '9') ||
(basename.lastChar() >= 'B' && basename.lastChar() <= 'Z')) {
basename.setChar(basename.lastChar()-1, basename.size()-1);
- return openFile(basename + "." + extension, fileIndex+1);
+ return loadFile(basename + "." + extension, fileIndex+1);
} else
- error ("Could not find file \'%s\'", filename.c_str());
+ error("Could not find file \'%s\'", filename.c_str());
}
if (fileIndex >= fileCount)
diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h
index 5e81f77a26..6cb175c689 100644
--- a/engines/startrek/startrek.h
+++ b/engines/startrek/startrek.h
@@ -36,6 +36,7 @@
#include "startrek/filestream.h"
#include "startrek/graphics.h"
+#include "startrek/object.h"
#include "startrek/room.h"
#include "startrek/sound.h"
@@ -58,10 +59,25 @@ enum StarTrekGameFeatures {
};
enum kDebugLevels {
- kDebugSound = 1 << 0
+ kDebugSound = 1 << 0,
+ kDebugGraphics = 1 << 1
};
+enum GameMode {
+ GAMEMODE_START = 0,
+ GAMEMODE_BRIDGE,
+ GAMEMODE_AWAYMISSION,
+ GAMEMODE_BEAMDOWN,
+ GAMEMODE_BEAMUP
+};
+
+enum TextDisplayMode {
+ TEXTDISPLAY_WAIT = 0, // Wait for input before closing text
+ TEXTDISPLAY_SUBTITLES, // Automatically continue when speech is done
+ TEXTDISPLAY_NONE // No text displayed
+};
+
enum TrekEventType {
TREKEVENT_TICK = 0, // DOS clock changes (see updateClockTicks)
TREKEVENT_LBUTTONDOWN = 1,
@@ -72,12 +88,6 @@ enum TrekEventType {
TREKEVENT_KEYDOWN = 6
};
-enum TextDisplayMode {
- TEXTDISPLAY_WAIT = 0, // Wait for input before closing text
- TEXTDISPLAY_SUBTITLES, // Automatically continue when speech is done
- TEXTDISPLAY_NONE // No text displayed
-};
-
struct TrekEvent {
TrekEventType type;
Common::KeyState kbd;
@@ -85,6 +95,8 @@ struct TrekEvent {
uint32 tick;
};
+const int MAX_OBJECTS = 0x20;
+
struct StarTrekGameDescription;
class Graphics;
class Sound;
@@ -93,6 +105,11 @@ class StarTrekEngine : public ::Engine {
protected:
Common::Error run();
+private:
+ // Game modes
+ Common::Error runGameMode(int mode);
+ void runTransportSequence(const Common::String &name);
+
public:
StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gamedesc);
virtual ~StarTrekEngine();
@@ -105,6 +122,18 @@ public:
void playSpeech(const Common::String &filename);
void stopPlayingSpeech();
+ // Objects
+ void initObjects();
+ int loadAnimationForObject(int objectIndex, const Common::String &animName, uint16 x, uint16 y, uint16 arg8);
+ void updateObjectAnimations();
+ void removeObjectFromScreen(int objectIndex);
+ void objectFunc1();
+ void drawObjectToScreen(Object *object, const Common::String &animName, uint16 field5e, uint16 field60, uint16 arg8, bool addSprite);
+ void releaseAnim(Object *object);
+
+ SharedPtr<Bitmap> loadAnimationFrame(const Common::String &filename, uint16 arg2);
+ Common::String getCrewmanAnimFilename(int objectIndex, const Common::String &basename);
+
// Events
public:
void initializeEventsAndMouse();
@@ -138,14 +167,30 @@ public:
Common::Language getLanguage();
// Resource related functions
- SharedPtr<FileStream> openFile(Common::String filename, int fileIndex=0);
+ SharedPtr<FileStream> loadFile(Common::String filename, int fileIndex=0);
// Movie related functions
void playMovie(Common::String filename);
void playMovieMac(Common::String filename);
+public:
+ int _gameMode;
+ int _lastGameMode;
+ bool _redshirtDead;
+ Common::String _missionToLoad;
+
+ Object _objectList[MAX_OBJECTS];
+ Object * const _kirkObject;
+ Object * const _spockObject;
+ Object * const _mccoyObject;
+ Object * const _redshirtObject;
+
+ SharedPtr<FileStream> _objectBanFiles[MAX_OBJECTS / 2];
+ uint16 _objectBanVar2[MAX_OBJECTS / 2]; // TODO: initialize?
+
uint32 _clockTicks;
+ uint32 _frameIndex;
bool _musicEnabled;
bool _sfxEnabled;
diff --git a/engines/startrek/text.cpp b/engines/startrek/text.cpp
index 923ebc6c8b..ef5a746756 100644
--- a/engines/startrek/text.cpp
+++ b/engines/startrek/text.cpp
@@ -68,7 +68,7 @@ int Graphics::showText(TextGetterFunc textGetter, uintptr var, int xoffset, int
int16 tmpTextDisplayMode = _textDisplayMode;
uint32 var7c = 8;
- if (_textboxVar3 > _textboxVar2+1) {
+ if (_vm->_frameIndex > _textboxVar2+1) {
var7c = 0x10;
}
@@ -291,7 +291,7 @@ reloadText:
// sub_272B4
}
- _textboxVar2 = _textboxVar3;
+ _textboxVar2 = _vm->_frameIndex;
_vm->stopPlayingSpeech();
return choiceIndex;
}
@@ -347,7 +347,7 @@ int Graphics::handleMenuEvents(uint32 ticksUntilClickingEnabled, bool arg4) {
}
}
// sub_1E88C();
- _textboxVar3++;
+ _vm->_frameIndex++;
if (ticksUntilClickingEnabled != 0 && _vm->_clockTicks >= tickWhenClickingEnabled)
return MENUEVENT_ENABLEINPUT;
@@ -818,7 +818,7 @@ void Graphics::loadMenuButtons(String mnuFilename, int xpos, int ypos) {
_activeMenu = SharedPtr<Menu>(new Menu());
_activeMenu->nextMenu = oldMenu;
- SharedPtr<FileStream> stream = _vm->openFile(mnuFilename + ".MNU");
+ SharedPtr<FileStream> stream = _vm->loadFile(mnuFilename + ".MNU");
_activeMenu->menuFile = stream;
_activeMenu->numButtons = _activeMenu->menuFile->size() / 16;