Permalink
Browse files

STARTREK: Fix sound, support MT32.

Also jump to the first mission after the intro.
  • Loading branch information...
Drenn1 authored and sev- committed Jul 18, 2018
1 parent 52cfe60 commit 639c02b76f591fe17ee78b6a72da46c4782fd4d5
Showing with 129 additions and 114 deletions.
  1. +83 −76 engines/startrek/events.cpp
  2. +2 −10 engines/startrek/graphics.cpp
  3. +2 −2 engines/startrek/sound.cpp
  4. +30 −23 engines/startrek/startrek.cpp
  5. +12 −3 engines/startrek/startrek.h
@@ -23,89 +23,72 @@

namespace StarTrek {

/**
* Doesn't return until an event occurs.
*/
void StarTrekEngine::pollSystemEvents(bool queueEvents) {
void StarTrekEngine::pollEvents(bool queueEvents) {
Common::Event event;
TrekEvent trekEvent;
while (_eventMan->pollEvent(event)) {
trekEvent.mouse = event.mouse;
trekEvent.kbd = event.kbd;

switch (event.type) {
case Common::EVENT_QUIT:
_system->quit();
break;

while (!queueEvents || _eventQueue.empty()) {
while (_eventMan->pollEvent(event)) {
trekEvent.mouse = event.mouse;
trekEvent.kbd = event.kbd;

switch (event.type) {
case Common::EVENT_QUIT:
_system->quit();
break;

case Common::EVENT_MOUSEMOVE:
if (queueEvents) {
trekEvent.type = TREKEVENT_MOUSEMOVE;
addEventToQueue(trekEvent);
}

// WORKAROUND: this improves the responsiveness of the mouse.
_system->updateScreen();
break;

case Common::EVENT_LBUTTONDOWN:
if (queueEvents) {
trekEvent.type = TREKEVENT_LBUTTONDOWN;
addEventToQueue(trekEvent);
}
break;

case Common::EVENT_RBUTTONDOWN:
if (queueEvents) {
trekEvent.type = TREKEVENT_RBUTTONDOWN;
addEventToQueue(trekEvent);
}
break;

case Common::EVENT_KEYDOWN:
if (queueEvents) {
trekEvent.type = TREKEVENT_KEYDOWN;
addEventToQueue(trekEvent);
}
break;

default:
break;
case Common::EVENT_MOUSEMOVE:
if (queueEvents) {
trekEvent.type = TREKEVENT_MOUSEMOVE;
addEventToQueue(trekEvent);
}
}

// Check for tick event
uint nextFrame = _frameStartMillis + 1000 / 18.206;
uint millis = _system->getMillis();
// WORKAROUND: this improves the responsiveness of the mouse.
_system->updateScreen();
break;

if (millis >= nextFrame) {
_clockTicks++;
case Common::EVENT_LBUTTONDOWN:
if (queueEvents) {
trekEvent.type = TREKEVENT_LBUTTONDOWN;
addEventToQueue(trekEvent);
}
break;

_frameStartMillis = millis;
case Common::EVENT_RBUTTONDOWN:
if (queueEvents) {
trekEvent.type = TREKEVENT_RBUTTONDOWN;
addEventToQueue(trekEvent);
}
break;

case Common::EVENT_KEYDOWN:
if (queueEvents) {
TrekEvent tickEvent;
tickEvent.type = TREKEVENT_TICK;
tickEvent.tick = _clockTicks;
addEventToQueue(tickEvent);
trekEvent.type = TREKEVENT_KEYDOWN;
addEventToQueue(trekEvent);
}
}
break;

if (queueEvents && !_eventQueue.empty())
default:
break;
}
}
}

// Wait a 60th of a second before checking for events again
int delay = 1000 / 60;
millis = _system->getMillis();
if (millis + delay > nextFrame)
delay = nextFrame - millis;
if (delay > 0)
_system->delayMillis(delay);
void StarTrekEngine::waitForNextTick(bool queueEvents) {
pollEvents(queueEvents);

if (!queueEvents)
break;
uint nextFrame = _frameStartMillis + 1000 / 18.206;
uint millis = _system->getMillis();

if (millis < nextFrame)
_system->delayMillis(nextFrame - millis);

_clockTicks++;
_frameStartMillis = nextFrame;

if (queueEvents) {
TrekEvent tickEvent;
tickEvent.type = TREKEVENT_TICK;
tickEvent.tick = _clockTicks;
addEventToQueue(tickEvent);
}
}

@@ -117,11 +100,35 @@ void StarTrekEngine::initializeEventsAndMouse() {
// TODO: mouse
}

/**
* Returns false if there is no event waiting.
*/
bool StarTrekEngine::getNextEvent(TrekEvent *e) {
pollSystemEvents(); // TODO: put this somewhere else?
bool StarTrekEngine::getNextEvent(TrekEvent *e, bool poll) {
while (poll && _eventQueue.empty()) {
pollEvents(true);

// Check for tick event
uint nextFrame = _frameStartMillis + 1000 / 18.206;
uint millis = _system->getMillis();

if (millis >= nextFrame) {
_clockTicks++;
_frameStartMillis = millis;

TrekEvent tickEvent;
tickEvent.type = TREKEVENT_TICK;
tickEvent.tick = _clockTicks;
addEventToQueue(tickEvent);
}

if (!_eventQueue.empty())
break;

// Still no events; wait a 60th of a second before checking for events again
int delay = 1000 / 60;
millis = _system->getMillis();
if (millis + delay > nextFrame)
delay = nextFrame - millis;
if (delay > 0)
_system->delayMillis(delay);
}

if (_eventQueue.empty())
return false;
@@ -143,8 +150,8 @@ void StarTrekEngine::removeNextEvent() {
_eventQueue.pop_front();
}

bool StarTrekEngine::popNextEvent(TrekEvent *e) {
if (!getNextEvent(e))
bool StarTrekEngine::popNextEvent(TrekEvent *e, bool poll) {
if (!getNextEvent(e, poll))
return false;

removeNextEvent();
@@ -134,11 +134,7 @@ void Graphics::loadPalette(const Common::String &paletteName) {
void Graphics::fadeinScreen() {
while (_paletteFadeLevel <= 100) {
TrekEvent event;
do {
if (!_vm->popNextEvent(&event))
continue;
}
while (event.type != TREKEVENT_TICK);
_vm->waitForNextTick();

setPaletteFadeLevel(_palData, _paletteFadeLevel);
_paletteFadeLevel += 10;
@@ -150,11 +146,7 @@ void Graphics::fadeinScreen() {
void Graphics::fadeoutScreen() {
while (_paletteFadeLevel >= 0) {
TrekEvent event;
do {
if (!_vm->popNextEvent(&event))
continue;
}
while (event.type != TREKEVENT_TICK);
_vm->waitForNextTick();

setPaletteFadeLevel(_palData, _paletteFadeLevel);
_paletteFadeLevel -= 10;
@@ -36,7 +36,7 @@ namespace StarTrek {

Sound::Sound(StarTrekEngine *vm) : _vm(vm) {
if (_vm->getPlatform() == Common::kPlatformDOS || _vm->getPlatform() == Common::kPlatformMacintosh) {
_midiDevice = MidiDriver::detectDevice(MDT_PCSPK|MDT_ADLIB|MDT_MIDI);
_midiDevice = MidiDriver::detectDevice(MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32);
_midiDriver = MidiDriver::createMidi(_midiDevice);
_midiDriver->open();
_midiDriver->setTimerCallback(this, Sound::midiDriverCallback);
@@ -366,7 +366,7 @@ void Sound::clearMidiSlot(int slot) {
// Static callback method
void Sound::midiDriverCallback(void *data) {
Sound *s = (Sound*)data;
for (int i = NUM_MIDI_SLOTS; i < NUM_MIDI_SLOTS; i++)
for (int i = 0; i < NUM_MIDI_SLOTS; i++)
s->_midiSlots[i].midiParser->onTimer();

// TODO: put this somewhere other than the midi callback...
@@ -87,7 +87,7 @@ StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gam
_missionToLoad = "DEMON";
_roomIndexToLoad = 0;

_showSubtitles = false; // TODO: test
_showSubtitles = true; // TODO: test

for (int i = 0; i < NUM_OBJECTS; i++)
_itemList[i] = g_itemList[i];
@@ -116,13 +116,14 @@ Common::Error StarTrekEngine::run() {

_frameIndex = 0;
playIntro();
debug("DONE");

_frameIndex = 0;

_gameMode = -1;
_lastGameMode = -1;

runGameMode(GAMEMODE_START);
runGameMode(GAMEMODE_AWAYMISSION);
return Common::kNoError;
}

@@ -229,11 +230,11 @@ void StarTrekEngine::playIntro() {

uint32 clockTicks = _clockTicks;

Sprite sprite;
_gfx->addSprite(&sprite);
sprite.setXYAndPriority(0, 0, 12);
sprite.bitmap = _gfx->loadBitmap("blank");
sprite.drawPriority2 = 16;
Sprite subtitleSprite;
_gfx->addSprite(&subtitleSprite);
subtitleSprite.setXYAndPriority(0, 0, 12);
subtitleSprite.bitmap = _gfx->loadBitmap("blank");
subtitleSprite.drawPriority2 = 16;

int index = 12;
while (index >= 0) {
@@ -268,7 +269,7 @@ void StarTrekEngine::playIntro() {
clockTicks += 540;

while (_clockTicks < clockTicks && _sound->isMidiPlaying()) {
pollSystemEvents(false);
waitForNextTick(true);
}

// TODO: MT audio file
@@ -281,16 +282,18 @@ void StarTrekEngine::playIntro() {

int32 starfieldZoomSpeed;
int16 frame = 0;
bool buttonPressed = 0;
bool buttonPressed = false;

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;
if (!buttonPressed) {
TrekEvent event;
while (popNextEvent(&event, false)) {
if (event.type == TREKEVENT_KEYDOWN) {
_gfx->fadeoutScreen();
buttonPressed = true;
} else if (event.type == TREKEVENT_TICK)
break;
}
}

switch (frame) {
@@ -302,15 +305,20 @@ void StarTrekEngine::playIntro() {

case 30:
_sound->playVoc("kirkintr");
loadSubtitleSprite(0, &sprite);
loadSubtitleSprite(0, &subtitleSprite);
break;

case 36:
loadSubtitleSprite(1, &sprite);
loadSubtitleSprite(1, &subtitleSprite);
break;

case 42:
loadSubtitleSprite(-1, &sprite);
loadSubtitleSprite(-1, &subtitleSprite);
break;

case 378:
_gfx->delSprite(&subtitleSprite);
_byte_45b3c = 1;
break;
}

@@ -321,7 +329,7 @@ void StarTrekEngine::playIntro() {
clockTicks += 3;

while (_clockTicks < clockTicks)
pollSystemEvents(false);
waitForNextTick();
}

_starfieldPosition.z += starfieldZoomSpeed;
@@ -418,10 +426,9 @@ void StarTrekEngine::drawStarfield() {
file->seek(fileOffset, SEEK_SET);
SharedPtr<Bitmap> bitmap = SharedPtr<Bitmap>(new Bitmap(file));

if (!drawRect.isEmpty()) {
if (!drawRect.isEmpty())
_gfx->drawBitmapToBackground(starRect, drawRect, bitmap);
bitmap.reset();
}
bitmap.reset();
} else {
star->active = false;

@@ -339,11 +339,20 @@ class StarTrekEngine : public ::Engine {

// Events
public:
void pollSystemEvents(bool queueEvents = true);
/**
* Checks for all events, and updates Star Trek's event queue if queueEvents is set.
* This does not account for "tick" events (getNextEvent/popNextEvent handle that).
*/
void pollEvents(bool queueEvents = true);
void waitForNextTick(bool queueEvents = true);
void initializeEventsAndMouse();
bool getNextEvent(TrekEvent *e);
/**
* Returns false if there is no event waiting. If "poll" is true, this always returns
* something (waits until an event occurs if necessary).
*/
bool getNextEvent(TrekEvent *e, bool poll = true);
void removeNextEvent();
bool popNextEvent(TrekEvent *e);
bool popNextEvent(TrekEvent *e, bool poll = true);
void addEventToQueue(const TrekEvent &e);
void clearEventBuffer();
void updateEvents();

0 comments on commit 639c02b

Please sign in to comment.