Permalink
Browse files

STARTREK: Get starfields working for the intro

  • Loading branch information...
Drenn1 authored and sev- committed Jul 17, 2018
1 parent b9eca08 commit 52cfe602712ad39174379d56e1b45b7121fefda6
@@ -30,16 +30,28 @@ 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) {
pixels = new byte[width*height];
}

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;
}

}
@@ -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
@@ -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;
}
}

@@ -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 {
@@ -46,6 +46,7 @@ class FileStream {

byte readByte();
uint16 readUint16();
uint32 readUint32();

// SeekableReadStream functions
int32 pos() const;
@@ -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();
}

/**
@@ -52,7 +52,15 @@ class Graphics {
~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();
@@ -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...
@@ -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 @@ class Sound {
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 @@ class Sound {

// 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;
Oops, something went wrong.

0 comments on commit 52cfe60

Please sign in to comment.