diff options
author | Matthew Stewart | 2018-07-17 04:10:48 -0400 |
---|---|---|
committer | Eugene Sandulenko | 2018-08-09 08:37:30 +0200 |
commit | 52cfe602712ad39174379d56e1b45b7121fefda6 (patch) | |
tree | 32f9a3fca6f557c930afa3dd93bb93c1b306219a /engines | |
parent | b9eca08db639299cfa13385db45b84b0b01cda28 (diff) | |
download | scummvm-rg350-52cfe602712ad39174379d56e1b45b7121fefda6.tar.gz scummvm-rg350-52cfe602712ad39174379d56e1b45b7121fefda6.tar.bz2 scummvm-rg350-52cfe602712ad39174379d56e1b45b7121fefda6.zip |
STARTREK: Get starfields working for the intro
Diffstat (limited to 'engines')
-rw-r--r-- | engines/startrek/bitmap.cpp | 27 | ||||
-rw-r--r-- | engines/startrek/bitmap.h | 13 | ||||
-rw-r--r-- | engines/startrek/events.cpp | 55 | ||||
-rw-r--r-- | engines/startrek/filestream.cpp | 11 | ||||
-rw-r--r-- | engines/startrek/filestream.h | 1 | ||||
-rw-r--r-- | engines/startrek/graphics.cpp | 40 | ||||
-rw-r--r-- | engines/startrek/graphics.h | 10 | ||||
-rw-r--r-- | engines/startrek/sound.cpp | 28 | ||||
-rw-r--r-- | engines/startrek/sound.h | 5 | ||||
-rw-r--r-- | engines/startrek/startrek.cpp | 293 | ||||
-rw-r--r-- | engines/startrek/startrek.h | 72 |
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; |