aboutsummaryrefslogtreecommitdiff
path: root/engines/startrek
diff options
context:
space:
mode:
authorMatthew Stewart2018-07-17 04:10:48 -0400
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commit52cfe602712ad39174379d56e1b45b7121fefda6 (patch)
tree32f9a3fca6f557c930afa3dd93bb93c1b306219a /engines/startrek
parentb9eca08db639299cfa13385db45b84b0b01cda28 (diff)
downloadscummvm-rg350-52cfe602712ad39174379d56e1b45b7121fefda6.tar.gz
scummvm-rg350-52cfe602712ad39174379d56e1b45b7121fefda6.tar.bz2
scummvm-rg350-52cfe602712ad39174379d56e1b45b7121fefda6.zip
STARTREK: Get starfields working for the intro
Diffstat (limited to 'engines/startrek')
-rw-r--r--engines/startrek/bitmap.cpp27
-rw-r--r--engines/startrek/bitmap.h13
-rw-r--r--engines/startrek/events.cpp55
-rw-r--r--engines/startrek/filestream.cpp11
-rw-r--r--engines/startrek/filestream.h1
-rw-r--r--engines/startrek/graphics.cpp40
-rw-r--r--engines/startrek/graphics.h10
-rw-r--r--engines/startrek/sound.cpp28
-rw-r--r--engines/startrek/sound.h5
-rw-r--r--engines/startrek/startrek.cpp293
-rw-r--r--engines/startrek/startrek.h72
11 files changed, 515 insertions, 40 deletions
diff --git a/engines/startrek/bitmap.cpp b/engines/startrek/bitmap.cpp
index 19f1434388..2e6eb78d92 100644
--- a/engines/startrek/bitmap.cpp
+++ b/engines/startrek/bitmap.cpp
@@ -30,8 +30,19 @@ Bitmap::Bitmap(SharedPtr<FileStream> stream) {
width = stream->readUint16();
height = stream->readUint16();
- pixels = new byte[width*height];
- stream->read(pixels, width*height);
+ pixelsArraySize = width * height;
+ pixels = new byte[pixelsArraySize];
+ stream->read(pixels, width * height);
+}
+
+Bitmap::Bitmap(const Bitmap &bitmap) {
+ xoffset = bitmap.xoffset;
+ yoffset = bitmap.yoffset;
+ width = bitmap.width;
+ height = bitmap.height;
+ pixelsArraySize = bitmap.pixelsArraySize;
+ pixels = new byte[pixelsArraySize];
+ memcpy(pixels, bitmap.pixels, pixelsArraySize);
}
Bitmap::Bitmap(int w, int h) : width(w), height(h), xoffset(0), yoffset(0) {
@@ -39,7 +50,8 @@ Bitmap::Bitmap(int w, int h) : width(w), height(h), xoffset(0), yoffset(0) {
}
Bitmap::~Bitmap() {
- delete[] pixels;
+ if (pixels != nullptr)
+ delete[] pixels;
}
@@ -49,7 +61,14 @@ TextBitmap::TextBitmap(int w, int h) {
// Width and Height are the total dimensions. Since each character takes 8 pixels in
// each dimension, the "pixels" array (which actually stores character indices) must
// be smaller.
- pixels = new byte[width/8*height/8];
+ pixelsArraySize = width / 8 * height / 8;
+ pixels = new byte[pixelsArraySize];
+}
+
+StubBitmap::StubBitmap(int w, int h) {
+ width = w;
+ height = h;
+ pixelsArraySize = 0;
}
}
diff --git a/engines/startrek/bitmap.h b/engines/startrek/bitmap.h
index b4c7a87115..8bc9cd2952 100644
--- a/engines/startrek/bitmap.h
+++ b/engines/startrek/bitmap.h
@@ -16,11 +16,13 @@ struct Bitmap {
byte *pixels;
Bitmap(Common::SharedPtr<FileStream> stream);
+ Bitmap(const Bitmap &bitmap);
Bitmap(int w, int h);
~Bitmap();
protected:
- Bitmap() : xoffset(0),yoffset(0),width(0),height(0),pixels(nullptr) {}
+ int32 pixelsArraySize;
+ Bitmap() : xoffset(0),yoffset(0),width(0),height(0),pixels(nullptr),pixelsArraySize(0) {}
};
@@ -32,6 +34,15 @@ struct TextBitmap : Bitmap {
TextBitmap(int w, int h);
};
+
+// StubBitmap is a bitmap without any actual pixel data. Used as a stub for the
+// "starfield" sprite, which is always in draw mode 1 (invisible), so it never gets drawn;
+// however, it does trigger refreshes on the background in that area, so the game can draw
+// on the background layer manually.
+struct StubBitmap : Bitmap {
+ StubBitmap(int w, int h);
+};
+
}
#endif
diff --git a/engines/startrek/events.cpp b/engines/startrek/events.cpp
index 88bca9d6ed..4685fded59 100644
--- a/engines/startrek/events.cpp
+++ b/engines/startrek/events.cpp
@@ -26,11 +26,11 @@ namespace StarTrek {
/**
* Doesn't return until an event occurs.
*/
-void StarTrekEngine::pollSystemEvents() {
+void StarTrekEngine::pollSystemEvents(bool queueEvents) {
Common::Event event;
TrekEvent trekEvent;
- while (_eventQueue.empty()) {
+ while (!queueEvents || _eventQueue.empty()) {
while (_eventMan->pollEvent(event)) {
trekEvent.mouse = event.mouse;
trekEvent.kbd = event.kbd;
@@ -41,26 +41,34 @@ void StarTrekEngine::pollSystemEvents() {
break;
case Common::EVENT_MOUSEMOVE:
- trekEvent.type = TREKEVENT_MOUSEMOVE;
- addEventToQueue(trekEvent);
+ if (queueEvents) {
+ trekEvent.type = TREKEVENT_MOUSEMOVE;
+ addEventToQueue(trekEvent);
+ }
// WORKAROUND: this improves the responsiveness of the mouse.
_system->updateScreen();
break;
case Common::EVENT_LBUTTONDOWN:
- trekEvent.type = TREKEVENT_LBUTTONDOWN;
- addEventToQueue(trekEvent);
+ if (queueEvents) {
+ trekEvent.type = TREKEVENT_LBUTTONDOWN;
+ addEventToQueue(trekEvent);
+ }
break;
case Common::EVENT_RBUTTONDOWN:
- trekEvent.type = TREKEVENT_RBUTTONDOWN;
- addEventToQueue(trekEvent);
+ if (queueEvents) {
+ trekEvent.type = TREKEVENT_RBUTTONDOWN;
+ addEventToQueue(trekEvent);
+ }
break;
case Common::EVENT_KEYDOWN:
- trekEvent.type = TREKEVENT_KEYDOWN;
- addEventToQueue(trekEvent);
+ if (queueEvents) {
+ trekEvent.type = TREKEVENT_KEYDOWN;
+ addEventToQueue(trekEvent);
+ }
break;
default:
@@ -70,27 +78,34 @@ void StarTrekEngine::pollSystemEvents() {
// Check for tick event
uint nextFrame = _frameStartMillis + 1000 / 18.206;
+ uint millis = _system->getMillis();
- if (_system->getMillis() >= nextFrame) {
+ if (millis >= nextFrame) {
_clockTicks++;
- _frameStartMillis = _system->getMillis();
+ _frameStartMillis = millis;
- TrekEvent tickEvent;
- tickEvent.type = TREKEVENT_TICK;
- tickEvent.tick = _clockTicks;
- addEventToQueue(tickEvent);
+ if (queueEvents) {
+ TrekEvent tickEvent;
+ tickEvent.type = TREKEVENT_TICK;
+ tickEvent.tick = _clockTicks;
+ addEventToQueue(tickEvent);
+ }
}
- if (!_eventQueue.empty())
+ if (queueEvents && !_eventQueue.empty())
break;
// Wait a 60th of a second before checking for events again
- uint delay = 1000 / 60;
- if (_system->getMillis() + delay > nextFrame)
- delay = nextFrame - _system->getMillis();
+ int delay = 1000 / 60;
+ millis = _system->getMillis();
+ if (millis + delay > nextFrame)
+ delay = nextFrame - millis;
if (delay > 0)
_system->delayMillis(delay);
+
+ if (!queueEvents)
+ break;
}
}
diff --git a/engines/startrek/filestream.cpp b/engines/startrek/filestream.cpp
index 31cb789a88..ed54744fd8 100644
--- a/engines/startrek/filestream.cpp
+++ b/engines/startrek/filestream.cpp
@@ -42,6 +42,17 @@ uint16 FileStream::readUint16() {
return w;
}
+uint32 FileStream::readUint32() {
+ assert(_pos + 4 <= size());
+ uint32 w;
+ if (_bigEndian)
+ w = _data[_pos + 3] | (_data[_pos + 2] << 8) | (_data[_pos + 1] << 16) | (_data[_pos] << 24);
+ else
+ w = _data[_pos] | (_data[_pos + 1] << 8) | (_data[_pos + 2] << 16) | (_data[_pos + 3] << 24);
+ _pos += 4;
+ return w;
+}
+
// SeekableReadStream functions
int32 FileStream::pos() const {
diff --git a/engines/startrek/filestream.h b/engines/startrek/filestream.h
index 79a919ac22..a3d9381101 100644
--- a/engines/startrek/filestream.h
+++ b/engines/startrek/filestream.h
@@ -46,6 +46,7 @@ public:
byte readByte();
uint16 readUint16();
+ uint32 readUint32();
// SeekableReadStream functions
int32 pos() const;
diff --git a/engines/startrek/graphics.cpp b/engines/startrek/graphics.cpp
index 753605a494..9b1801b47f 100644
--- a/engines/startrek/graphics.cpp
+++ b/engines/startrek/graphics.cpp
@@ -73,7 +73,45 @@ Graphics::~Graphics() {
void Graphics::setBackgroundImage(SharedPtr<Bitmap> bitmap) {
- _backgroundImage = bitmap;
+ _backgroundImage = SharedPtr<Bitmap>(new Bitmap(*bitmap));
+}
+
+void Graphics::drawBitmapToBackground(const Common::Rect &origRect, const Common::Rect &drawRect, SharedPtr<Bitmap> bitmap) {
+ byte *dest = _backgroundImage->pixels + drawRect.top * SCREEN_WIDTH + drawRect.left;
+ byte *src = bitmap->pixels + (drawRect.left - origRect.left)
+ + (drawRect.top - origRect.top) * bitmap->width;
+
+ for (int y = drawRect.top; y < drawRect.bottom; y++) {
+ for (int x = drawRect.left; x < drawRect.right; x++) {
+ byte b = *src;
+
+ if (b != 0)
+ *dest = b;
+
+ src++;
+ dest++;
+ }
+
+ src += bitmap->width - drawRect.width();
+ dest += SCREEN_WIDTH - drawRect.width();
+ }
+}
+
+void Graphics::fillBackgroundRect(const Common::Rect &rect, byte color) {
+ byte *dest = _backgroundImage->pixels + rect.top * SCREEN_WIDTH + rect.left;
+ for (int y = rect.top; y < rect.bottom; y++) {
+ memset(dest, color, rect.width());
+ dest += SCREEN_WIDTH;
+ }
+}
+
+void Graphics::clearScreenAndPriBuffer() {
+ Common::fill(_priData, _priData + sizeof(_priData), 0);
+
+ ::Graphics::Surface *surface = _vm->_system->lockScreen();
+ surface->fillRect(_screenRect, 0);
+ _vm->_system->unlockScreen();
+ _vm->_system->updateScreen();
}
/**
diff --git a/engines/startrek/graphics.h b/engines/startrek/graphics.h
index 37ac7da94c..a40e1fa2f4 100644
--- a/engines/startrek/graphics.h
+++ b/engines/startrek/graphics.h
@@ -52,7 +52,15 @@ public:
~Graphics();
void setBackgroundImage(SharedPtr<Bitmap> bitmap);
-
+ /**
+ * @param origRect The rectangle containing the original bitmap (must contain the
+ * whole bitmap, even if some is outside the drawable space)
+ * @param drawRect The clipped rectangle to draw at (must be within the drawable space)
+ */
+ void drawBitmapToBackground(const Common::Rect &origRect, const Common::Rect &drawRect, SharedPtr<Bitmap> bitmap);
+ void fillBackgroundRect(const Common::Rect &rect, byte color);
+
+ void clearScreenAndPriBuffer();
void loadPalette(const String &paletteFile);
void fadeinScreen();
void fadeoutScreen();
diff --git a/engines/startrek/sound.cpp b/engines/startrek/sound.cpp
index 46867961ae..b07fc68892 100644
--- a/engines/startrek/sound.cpp
+++ b/engines/startrek/sound.cpp
@@ -41,7 +41,7 @@ Sound::Sound(StarTrekEngine *vm) : _vm(vm) {
_midiDriver->open();
_midiDriver->setTimerCallback(this, Sound::midiDriverCallback);
- for (int i=0; i<8; i++) {
+ for (int i = 0; i < NUM_MIDI_SLOTS; i++) {
_midiSlots[i].slot = i;
_midiSlots[i].track = -1;
@@ -59,7 +59,7 @@ Sound::Sound(StarTrekEngine *vm) : _vm(vm) {
_soundHandle = new Audio::SoundHandle();
loadedSoundData = nullptr;
- for (int i=1; i<8; i++) {
+ for (int i = 1; i < NUM_MIDI_SLOTS; i++) {
_midiSlotList.push_back(&_midiSlots[i]);
}
@@ -71,7 +71,7 @@ Sound::Sound(StarTrekEngine *vm) : _vm(vm) {
}
Sound::~Sound() {
- for (int i=0; i<8; i++)
+ for (int i = 0; i < NUM_MIDI_SLOTS; i++)
delete _midiSlots[i].midiParser;
delete _midiDriver;
delete _soundHandle;
@@ -80,7 +80,7 @@ Sound::~Sound() {
void Sound::clearAllMidiSlots() {
- for (int i=0; i<8; i++) {
+ for (int i=0; i < NUM_MIDI_SLOTS; i++) {
clearMidiSlot(i);
}
}
@@ -95,7 +95,7 @@ void Sound::playMidiTrack(int track) {
assert(loadedSoundData != nullptr);
// Check if a midi slot for this track exists already
- for (int i=1; i<8; i++) {
+ for (int i = 1; i < NUM_MIDI_SLOTS; i++) {
if (_midiSlots[i].track == track) {
debugC(6, kDebugSound, "Playing MIDI track %d (slot %d)", track, i);
_midiSlots[i].midiParser->loadMusic(loadedSoundData, sizeof(loadedSoundData));
@@ -128,6 +128,18 @@ void Sound::playMidiTrackInSlot(int slot, int track) {
}
}
+bool Sound::isMidiPlaying() {
+ if (!_vm->_musicWorking)
+ return false;
+
+ for (int i = 0; i < NUM_MIDI_SLOTS; i++) {
+ if (_midiSlots[i].midiParser->isPlaying())
+ return true;
+ }
+
+ return false;
+}
+
void Sound::loadMusicFile(const Common::String &baseSoundName) {
clearAllMidiSlots();
@@ -239,7 +251,7 @@ void Sound::playSpeech(const Common::String &basename) {
audioQueue->queueAudioStream(audioStream, DisposeAfterUse::YES);
}
- name.erase(0,i+1);
+ name.erase(0, i + 1);
}
if (audioQueue != nullptr) {
@@ -288,7 +300,7 @@ void Sound::setSfxEnabled(bool enable) {
_vm->_sfxEnabled = enable;
if (!enable) {
- for (int i = 1; i < 8; i++)
+ for (int i = 1; i < NUM_MIDI_SLOTS; i++)
clearMidiSlot(i);
}
@@ -354,7 +366,7 @@ void Sound::clearMidiSlot(int slot) {
// Static callback method
void Sound::midiDriverCallback(void *data) {
Sound *s = (Sound*)data;
- for (int i=0; i<8; i++)
+ for (int i = NUM_MIDI_SLOTS; i < NUM_MIDI_SLOTS; i++)
s->_midiSlots[i].midiParser->onTimer();
// TODO: put this somewhere other than the midi callback...
diff --git a/engines/startrek/sound.h b/engines/startrek/sound.h
index d5d2323680..f708456c02 100644
--- a/engines/startrek/sound.h
+++ b/engines/startrek/sound.h
@@ -101,6 +101,8 @@ enum MidiTracks {
// Max # of VOC files that can play at once
const int MAX_SFX_PLAYING = 4;
+const int NUM_MIDI_SLOTS = 8;
+
struct MidiPlaybackSlot {
int slot;
int track;
@@ -116,6 +118,7 @@ public:
void clearAllMidiSlots();
void playMidiTrack(int track);
void playMidiTrackInSlot(int slot, int track);
+ bool isMidiPlaying();
void loadMusicFile(const Common::String &baseSoundName);
void playMidiMusicTracks(int startTrack, int loopTrack);
void playVoc(const Common::String &baseSoundName);
@@ -135,7 +138,7 @@ private:
// MIDI-Related Variables
MidiDriver *_midiDriver;
- MidiPlaybackSlot _midiSlots[8]; // 0 is for music; 1-7 are for sfx
+ MidiPlaybackSlot _midiSlots[NUM_MIDI_SLOTS]; // 0 is for music; 1-7 are for sfx
Common::List<MidiPlaybackSlot*> _midiSlotList; // Sorts midi slots by most recently used
byte *loadedSoundData;
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index fe496d22bd..f53ba176fb 100644
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -20,6 +20,7 @@
*
*/
+
#include "base/plugins.h"
#include "base/version.h"
#include "common/archive.h"
@@ -83,9 +84,11 @@ StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gam
_textboxVar6 = 0;
_textboxHasMultipleChoices = false;
- _missionToLoad = "TRIAL";
+ _missionToLoad = "DEMON";
_roomIndexToLoad = 0;
+ _showSubtitles = false; // TODO: test
+
for (int i = 0; i < NUM_OBJECTS; i++)
_itemList[i] = g_itemList[i];
}
@@ -112,11 +115,14 @@ Common::Error StarTrekEngine::run() {
initializeEventsAndMouse();
_frameIndex = 0;
+ playIntro();
+
+ _frameIndex = 0;
_gameMode = -1;
_lastGameMode = -1;
- runGameMode(GAMEMODE_AWAYMISSION);
+ runGameMode(GAMEMODE_START);
return Common::kNoError;
}
@@ -200,6 +206,274 @@ Common::Error StarTrekEngine::runGameMode(int mode) {
return Common::kNoError;
}
+void StarTrekEngine::playIntro() {
+ // TODO: .MT audio file
+
+ initStarfieldPosition();
+ initStarfield(10, 20, 309, 169, 128);
+
+ SharedPtr<Bitmap> fakeStarfieldBitmap(new StubBitmap(0, 0));
+ _starfieldSprite.bitmap = fakeStarfieldBitmap;
+ initStarfieldSprite(&_starfieldSprite, fakeStarfieldBitmap, _starfieldRect);
+
+ // TODO: remainder of starfield initialization
+
+ _gfx->clearScreenAndPriBuffer();
+ _gfx->fadeoutScreen();
+ _gfx->loadPalette("gold");
+ _gfx->setBackgroundImage(_gfx->loadBitmap("goldlogo"));
+ _sound->playVoc("logo");
+ _gfx->copyBackgroundScreen();
+ _system->updateScreen();
+ _gfx->fadeinScreen();
+
+ uint32 clockTicks = _clockTicks;
+
+ Sprite sprite;
+ _gfx->addSprite(&sprite);
+ sprite.setXYAndPriority(0, 0, 12);
+ sprite.bitmap = _gfx->loadBitmap("blank");
+ sprite.drawPriority2 = 16;
+
+ int index = 12;
+ while (index >= 0) {
+ Common::String file = Common::String::format("credit%02d.shp", index);
+ // TODO: This loads the file, but does not do anything with the resulting data, so
+ // this is just for caching it?
+ // Remember to deal with similar commented function calls below, too.
+ //loadFileWithParams(file, false, true, false);
+ index -= 1;
+ }
+
+ //loadFileWithParams("legal.bmp", false, true, false);
+
+ index = 6;
+ while (index >= 0) {
+ Common::String file = Common::String::format("tittxt%02d.bmp", index);
+ //loadFileWithParams(file, false, true, false);
+ index -= 1;
+ }
+
+ //loadFileWithParams("planet.shp", false, true, false);
+
+ index = 6;
+ while (index >= 0) {
+ Common::String file = Common::String::format("ent%d3.r3s", index);
+ //loadFileWithParams(file, false, true, false);
+ index -= 1;
+ }
+
+ // TODO: kirkintr
+
+ clockTicks += 540;
+
+ while (_clockTicks < clockTicks && _sound->isMidiPlaying()) {
+ pollSystemEvents(false);
+ }
+
+ // TODO: MT audio file
+
+ _gfx->fadeoutScreen();
+ _gfx->loadPalette("bridge");
+ _gfx->clearScreenAndPriBuffer();
+ _sound->loadMusicFile("title");
+ clockTicks = _clockTicks;
+
+ int32 starfieldZoomSpeed;
+ int16 frame = 0;
+ bool buttonPressed = 0;
+
+ while (frame != 0x180 || (_sound->isMidiPlaying() && !buttonPressed)) {
+ TrekEvent event;
+ while (popNextEvent(&event)) {
+ if (event.type == TREKEVENT_KEYDOWN) {
+ _gfx->fadeoutScreen();
+ buttonPressed = true;
+ } else if (event.type == TREKEVENT_TICK)
+ break;
+ }
+
+ switch (frame) {
+ case 0:
+ starfieldZoomSpeed = 10;
+ playMidiMusicTracks(MIDITRACK_0, -1);
+ _byte_45b3c = 0;
+ break;
+
+ case 30:
+ _sound->playVoc("kirkintr");
+ loadSubtitleSprite(0, &sprite);
+ break;
+
+ case 36:
+ loadSubtitleSprite(1, &sprite);
+ break;
+
+ case 42:
+ loadSubtitleSprite(-1, &sprite);
+ break;
+ }
+
+ if (!buttonPressed) {
+ updateStarfieldAndShips(false);
+ _gfx->drawAllSprites();
+ _gfx->incPaletteFadeLevel();
+ clockTicks += 3;
+
+ while (_clockTicks < clockTicks)
+ pollSystemEvents(false);
+ }
+
+ _starfieldPosition.z += starfieldZoomSpeed;
+
+ frame++;
+ if (frame >= 0x186)
+ frame = 0x186;
+ }
+
+ _gfx->fadeoutScreen();
+ _gfx->delSprite(&_starfieldSprite);
+ // TODO: the rest
+}
+
+void StarTrekEngine::loadSubtitleSprite(int index, Sprite *sprite) {
+ if (_showSubtitles) {
+ if (index == -1)
+ sprite->setBitmap(_gfx->loadBitmap("blank"));
+ else {
+ Common::String file = Common::String::format("tittxt%02d", index);
+ sprite->setBitmap(_gfx->loadBitmap(file));
+ }
+ }
+}
+
+void StarTrekEngine::initStarfieldPosition() {
+ memset(&_starfieldPosition, 0, sizeof(_starfieldPosition));
+ // TODO: matrix initialization
+}
+
+void StarTrekEngine::initStarfield(int16 x, int16 y, int16 width, int16 height, int16 arg8) {
+ _starfieldXVar1 = (x + width) / 2;
+ _starfieldYVar1 = (y + height) / 2;
+ _starfieldXVar2 = (width - x + 1) / 2;
+ _starfieldYVar2 = (height - y + 1) / 2;
+
+ _starfieldRect.left = _starfieldXVar1 - _starfieldXVar2;
+ _starfieldRect.right = _starfieldXVar1 + _starfieldXVar2;
+ _starfieldRect.top = _starfieldYVar1 - _starfieldYVar2;
+ _starfieldRect.bottom = _starfieldYVar1 + _starfieldYVar2;
+
+ memset(_starList, 0, sizeof(_starList));
+ _starfieldPointDivisor = 150;
+}
+
+void StarTrekEngine::clearStarfieldPixels() {
+ _gfx->fillBackgroundRect(_starfieldRect, 0);
+}
+
+void StarTrekEngine::drawStarfield() {
+ // TODO: make these class variables
+ Point3W starPositionWeightings[] = {{0x4000, 0, 0}, {0, 0x4000, 0}, {0, 0, 0x4000}};
+ float flt_50898 = 50.0; // ?
+
+ int16 var28 = ((_starfieldXVar2 * 3) >> 1);
+ int16 xvar = var28 / 2;
+ int16 var2a = ((_starfieldYVar2 * 3) >> 1);
+ int16 yvar = var2a / 2;
+ int16 var8 = _starfieldPointDivisor << 3;
+
+ SharedPtr<FileStream> file = loadFile("stars.shp");
+
+ for (int i = 0; i < NUM_STARS; i++) {
+ Star *star = &_starList[i];
+ if ((i & 0xf) == 0) {
+ file->seek(0, SEEK_SET);
+ }
+
+ if (!star->active) {
+ int16 var4 = getRandomWord() / var28 - xvar;
+ int16 var6 = getRandomWord() / var2a - yvar;
+ Point3 point = constructPoint3ForStarfield(var4, var6, var8);
+ star->pos = applyPointWeightings(starPositionWeightings, point) + _starfieldPosition;
+ star->active = true;
+ }
+
+ Point3 p = star->pos - _starfieldPosition;
+ Point3 point2 = applyPointWeightings2(p, starPositionWeightings);
+
+ if (point2.z > flt_50898 && point2.z < 0x3fff
+ && abs(point2.x) < point2.z && abs(point2.y) < point2.z) {
+
+ int16 x = _starfieldXVar1 + (point2.x * _starfieldPointDivisor / point2.z);
+ int16 y = _starfieldYVar1 - (point2.y * _starfieldPointDivisor / point2.z);
+
+ int fileOffset = file->pos();
+ file->readUint32();
+ int16 width = file->readUint16();
+ int16 height = file->readUint16();
+
+ Common::Rect starRect(x, y, x + width, y + height);
+ Common::Rect drawRect = _starfieldRect.findIntersectingRect(starRect);
+
+ file->seek(fileOffset, SEEK_SET);
+ SharedPtr<Bitmap> bitmap = SharedPtr<Bitmap>(new Bitmap(file));
+
+ if (!drawRect.isEmpty()) {
+ _gfx->drawBitmapToBackground(starRect, drawRect, bitmap);
+ bitmap.reset();
+ }
+ } else {
+ star->active = false;
+
+ file->readUint32();
+ int16 offset2 = file->readUint16() * file->readUint16();
+ file->seek(file->pos() + offset2, SEEK_SET);
+ }
+ }
+}
+
+void StarTrekEngine::updateStarfieldAndShips(bool arg0) {
+ _starfieldSprite.bitmapChanged = true;
+ // sub_24b74(...);
+ clearStarfieldPixels();
+ drawStarfield();
+
+ // TODO
+}
+
+Point3 StarTrekEngine::constructPoint3ForStarfield(int16 x, int16 y, int16 z) {
+ Point3 point;
+ point.z = z;
+ point.y = y * z / _starfieldPointDivisor;
+ point.x = x * z / _starfieldPointDivisor;
+
+ return point;
+}
+
+Point3 StarTrekEngine::applyPointWeightings(Point3W *weight, const Point3 &point) {
+ int32 ret[3];
+ for (int i = 0; i < 3; i++) {
+ ret[i] = weight[i].x * (point.x & 0xffff) + weight[i].y * (point.y & 0xffff) + weight[i].z * (point.z & 0xffff);
+ ret[i] <<= 2;
+ }
+ Point3 p;
+ p.x = ret[0] >> 16;
+ p.y = ret[1] >> 16;
+ p.z = ret[2] >> 16;
+ return p;
+}
+
+Point3 StarTrekEngine::applyPointWeightings2(const Point3 &point, Point3W *weight) {
+ Point3 p = Point3();
+ p.x = (weight[0].x * (point.x & 0xffff) + weight[1].x * (point.y & 0xffff) + weight[2].x * (point.z & 0xffff)) << 2;
+ p.y = (weight[0].y * (point.x & 0xffff) + weight[1].y * (point.y & 0xffff) + weight[2].y * (point.z & 0xffff)) << 2;
+ p.z = (weight[0].z * (point.x & 0xffff) + weight[1].z * (point.y & 0xffff) + weight[2].z * (point.z & 0xffff)) << 2;
+ p.x >>= 16;
+ p.y >>= 16;
+ p.z >>= 16;
+ return p;
+}
+
void StarTrekEngine::runTransportSequence(const Common::String &name) {
const uint16 crewmanTransportPositions[][2] = {
{ 0x8e, 0x7c },
@@ -1486,6 +1760,17 @@ exitWithoutSelection:
return lastItemIndex;
}
+void StarTrekEngine::initStarfieldSprite(Sprite *sprite, SharedPtr<Bitmap> bitmap, const Common::Rect &rect) {
+ sprite->setXYAndPriority(rect.left, rect.top, 0);
+ sprite->setBitmap(bitmap);
+ bitmap->xoffset = 0;
+ bitmap->yoffset = 0;
+ bitmap->width = rect.width();
+ bitmap->height = rect.height();
+ _gfx->addSprite(sprite);
+ sprite->drawMode = 1;
+}
+
/**
* A scale of 256 is the baseline.
*/
@@ -1801,6 +2086,10 @@ SharedPtr<FileStream> StarTrekEngine::loadFile(Common::String filename, int file
return SharedPtr<FileStream>();
}
+SharedPtr<FileStream> StarTrekEngine::loadFileWithParams(Common::String filename, bool unk1, bool unk2, bool unk3) {
+ return loadFile(filename);
+}
+
void StarTrekEngine::playMovie(Common::String filename) {
if (getPlatform() == Common::kPlatformMacintosh)
playMovieMac(filename);
diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h
index cacb8c3529..21981e2382 100644
--- a/engines/startrek/startrek.h
+++ b/engines/startrek/startrek.h
@@ -199,6 +199,43 @@ struct TrekEvent {
};
+// Pseudo-3D structs
+
+struct Point3 {
+ int32 x;
+ int32 y;
+ int32 z;
+
+ Point3 operator+(const Point3 &p) const {
+ Point3 p2;
+ p2.x = x + p.x;
+ p2.y = y + p.y;
+ p2.z = z + p.z;
+ return p2;
+ }
+ Point3 operator-(const Point3 &p) const {
+ Point3 p2;
+ p2.x = x - p.x;
+ p2.y = y - p.y;
+ p2.z = z - p.z;
+ return p2;
+ }
+};
+
+struct Point3W {
+ int16 x;
+ int16 y;
+ int16 z;
+};
+
+struct Star {
+ bool active;
+ Point3 pos;
+};
+
+#define NUM_STARS 16
+
+
struct StarTrekGameDescription;
class Graphics;
class IWFile;
@@ -237,6 +274,21 @@ public:
SharedPtr<Room> getRoom();
private:
+ // Intro
+ void playIntro();
+ void loadSubtitleSprite(int index, Sprite *sprite);
+
+ // Space, pseudo-3D
+ void initStarfieldPosition();
+ void initStarfield(int16 x, int16 y, int16 width, int16 height, int16 arg8);
+ void clearStarfieldPixels();
+ void drawStarfield();
+ void updateStarfieldAndShips(bool arg0);
+
+ Point3 constructPoint3ForStarfield(int16 x, int16 y, int16 z);
+ Point3 applyPointWeightings(Point3W *weight, const Point3 &point);
+ Point3 applyPointWeightings2(const Point3 &point, Point3W *weight);
+
// Transporter room
void runTransportSequence(const Common::String &name);
@@ -281,12 +333,13 @@ public:
void showInventoryIcons(bool showItem);
void hideInventoryIcons();
int showInventoryMenu(int x, int y, bool restoreMouse);
+ void initStarfieldSprite(Sprite *sprite, SharedPtr<Bitmap> bitmap, const Common::Rect &rect);
SharedPtr<Bitmap> scaleBitmap(SharedPtr<Bitmap> bitmap, Fixed16 scale);
void scaleBitmapRow(byte *src, byte *dest, uint16 origWidth, uint16 scaledWidth);
// Events
public:
- void pollSystemEvents();
+ void pollSystemEvents(bool queueEvents = true);
void initializeEventsAndMouse();
bool getNextEvent(TrekEvent *e);
void removeNextEvent();
@@ -391,6 +444,10 @@ public:
// Resource related functions
SharedPtr<FileStream> loadFile(Common::String filename, int fileIndex=0);
+ /**
+ * TODO: Figure out what the extra parameters are, and if they're important.
+ */
+ SharedPtr<FileStream> loadFileWithParams(Common::String filename, bool unk1, bool unk2, bool unk3);
// Movie related functions
void playMovie(Common::String filename);
@@ -477,7 +534,18 @@ public:
bool _keyboardControlsMouse;
bool _inQuitGameMenu;
-
+ bool _showSubtitles;
+
+ byte _byte_45b3c;
+
+ // Pseudo-3D / starfield stuff
+ Sprite _starfieldSprite;
+ Star _starList[NUM_STARS];
+ Point3 _starfieldPosition;
+ int32 _starfieldPointDivisor;
+ int16 _starfieldXVar1, _starfieldYVar1;
+ int16 _starfieldXVar2, _starfieldYVar2;
+ Common::Rect _starfieldRect;
Graphics *_gfx;
Sound *_sound;