Initial commit
This commit is contained in:
624
engines/kyra/sequence/seqplayer_eob_segacd.cpp
Normal file
624
engines/kyra/sequence/seqplayer_eob_segacd.cpp
Normal file
@@ -0,0 +1,624 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_EOB
|
||||
|
||||
#include "kyra/engine/eob.h"
|
||||
#include "kyra/graphics/screen_eob.h"
|
||||
#include "kyra/graphics/screen_eob_segacd.h"
|
||||
#include "kyra/resource/resource.h"
|
||||
#include "kyra/resource/resource_segacd.h"
|
||||
#include "kyra/sequence/seqplayer_eob_segacd.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
SegaSequencePlayer::SegaSequencePlayer(EoBEngine *vm, Screen_EoB *screen, SegaCDResource *res) : _vm(vm), _screen(screen), _res(res), _tileSets(0), _debugResyncCnt(0), _speechAnimType(0),
|
||||
_playingID(1), _waterdeepScene(0), _playSpeechAnimation(0), _frameTimer(0), _waterdeepSceneTimer(0), _speechAnimTimer(0), _speechAnimNo(0), _speechAnimFrame(0),
|
||||
_newTrack(-1), _pauseStart(0), _fastForward(false), _renderer(_screen->sega_getRenderer()), _animator(_screen->sega_getAnimator()) {
|
||||
#define SQOPC(x) _opcodes.push_back(new SQOpcode(this, &SegaSequencePlayer::x, #x))
|
||||
SQOPC(s_initDrawObject);
|
||||
SQOPC(s_drawTileSet);
|
||||
SQOPC(s_loadTileDataSingle);
|
||||
SQOPC(s_drawTileSetCustom);
|
||||
SQOPC(s_drawTileSetCustomTopToBottom);
|
||||
SQOPC(s_fillRect);
|
||||
SQOPC(s_void);
|
||||
SQOPC(s_initSprite);
|
||||
SQOPC(s_removeSprite);
|
||||
SQOPC(s_displayTextJp);
|
||||
SQOPC(s_fadeToNeutral);
|
||||
SQOPC(s_fadeToBlack);
|
||||
SQOPC(s_fadeToNeutral2);
|
||||
SQOPC(s_fadeToWhite);
|
||||
SQOPC(s_setPalette);
|
||||
SQOPC(s_vScroll);
|
||||
SQOPC(s_hScroll);
|
||||
SQOPC(s_paletteOps);
|
||||
SQOPC(s_initSpriteCustomCoords);
|
||||
SQOPC(s_fillRectWithPattern);
|
||||
SQOPC(s_loadTileDataSeries);
|
||||
SQOPC(s_drawTileSetSeries);
|
||||
SQOPC(s_initSpriteSeries);
|
||||
SQOPC(s_initSpriteCustom);
|
||||
SQOPC(s_drawTileSetCustomCoords);
|
||||
SQOPC(s_waitForPaletteFade);
|
||||
SQOPC(s_clearSprites);
|
||||
SQOPC(s_moveSprites2);
|
||||
SQOPC(s_moveSprites);
|
||||
SQOPC(s_moveMorphSprite);
|
||||
SQOPC(s_unpauseCD);
|
||||
SQOPC(s_toggleWaterDeepAnimations);
|
||||
SQOPC(s_assignSpeechAnimGraphics);
|
||||
SQOPC(s_toggleSpeechAnimation);
|
||||
SQOPC(s_orbZoomEffect);
|
||||
SQOPC(s_stopCD);
|
||||
SQOPC(s_playCD);
|
||||
SQOPC(s_displayTextEn);
|
||||
SQOPC(s_loadCustomPalettes);
|
||||
SQOPC(s_playSoundEffect);
|
||||
#undef SQOPC
|
||||
|
||||
_scrollManager = new ScrollManager(_renderer);
|
||||
assert(_scrollManager);
|
||||
_tileSets = new TileSet[100]();
|
||||
assert(_tileSets);
|
||||
_drawObjects = new DrawObject[100]();
|
||||
assert(_drawObjects);
|
||||
|
||||
memset(_speechAnimDrawOps, 0, sizeof(_speechAnimDrawOps));
|
||||
|
||||
_scaleSrcBuffer = new uint8[0x5800]();
|
||||
assert(_scaleSrcBuffer);
|
||||
_scaleOutBuffer = new uint8[0x5800]();
|
||||
assert(_scaleOutBuffer);
|
||||
_scaleStampMap = new uint16[0x100]();
|
||||
assert(_scaleStampMap);
|
||||
_scaleTraceVectors = new uint16[0x580]();
|
||||
assert(_scaleTraceVectors);
|
||||
|
||||
int temp;
|
||||
_wdDsX = _vm->staticres()->loadRawDataBe16(kEoB1IntroWdDsX, temp);
|
||||
_wdDsY = _vm->staticres()->loadRawData(kEoB1IntroWdDsY, temp);
|
||||
_wdAnimSprites = _vm->staticres()->loadRawData(kEoB1WdAnimSprites, temp);
|
||||
_speechAnimData = _vm->staticres()->loadRawData(kEoB1SpeechAnimData, temp);
|
||||
_cdaTracks = _vm->staticres()->loadRawData(kEoB1SequenceTrackMap, temp);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
_patternTables[i] = _vm->staticres()->loadRawDataBe16(kEoB1PatternTable0 + i, temp);
|
||||
}
|
||||
|
||||
SegaSequencePlayer::~SegaSequencePlayer() {
|
||||
delete[] _drawObjects;
|
||||
delete[] _tileSets;
|
||||
delete[] _scaleSrcBuffer;
|
||||
delete[] _scaleOutBuffer;
|
||||
delete[] _scaleStampMap;
|
||||
delete[] _scaleTraceVectors;
|
||||
|
||||
for (Common::Array<SQOpcode*>::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i)
|
||||
delete (*i);
|
||||
|
||||
delete _scrollManager;
|
||||
}
|
||||
|
||||
bool SegaSequencePlayer::play(int id) {
|
||||
_renderer->render(0);
|
||||
_screen->sega_fadeToBlack(2);
|
||||
_screen->clearPage(0);
|
||||
|
||||
_animator->clearSprites();
|
||||
_scrollManager->setVScrollTimers(0, 1, 0, 0, 1, 0);
|
||||
_scrollManager->setHScrollTimers(0, 1, 0, 0, 1, 0);
|
||||
_vm->_txt->clearDim(2);
|
||||
|
||||
_renderer->fillRectWithTiles(2, 0, 0, 40, 28, 0xE6C2);
|
||||
_renderer->fillRectWithTiles(0, 0, 0, 64, 42, 0);
|
||||
_renderer->fillRectWithTiles(1, 0, 0, 64, 28, 0);
|
||||
_renderer->fillRectWithTiles(2, 1, (id == 53 || id == 54) ? 22 : 20, 38, 6, 0xE51C, true);
|
||||
|
||||
_debugResyncCnt = 0;
|
||||
_playingID = id;
|
||||
_newTrack = -1;
|
||||
|
||||
_vm->_allowSkip = true;
|
||||
_vm->resetSkipFlag();
|
||||
|
||||
for (bool runLoop = true; runLoop && !(_vm->shouldQuit() || _vm->skipFlag()); ) {
|
||||
uint32 offset = (id - 1) * 0x3C000;
|
||||
if (id >= 54)
|
||||
offset -= 0x8000;
|
||||
if (id >= 55)
|
||||
offset -= 0x18000;
|
||||
|
||||
uint32 size = (id == 53) ? 0x34000 : ((id == 54) ? 0x24000 : 0x3C000);
|
||||
|
||||
if (!_res->loadContainer("VISUAL", offset, size))
|
||||
return false;
|
||||
|
||||
Common::SeekableReadStreamEndian *in = _res->resStreamEndian(0);
|
||||
if (!in)
|
||||
return false;
|
||||
_screen->sega_loadCustomPaletteData(in);
|
||||
delete in;
|
||||
|
||||
_screen->sega_selectPalette(31, 0, false);
|
||||
_screen->sega_selectPalette(32, 1, false);
|
||||
_screen->sega_selectPalette(30, 3, false);
|
||||
|
||||
in = _res->resStreamEndian(2);
|
||||
if (!in)
|
||||
return false;
|
||||
uint32 len = in->size();
|
||||
uint8 *tileData = new uint8[len];
|
||||
in->read(tileData, len);
|
||||
delete in;
|
||||
|
||||
in = _res->resStreamEndian(1);
|
||||
if (!in)
|
||||
return false;
|
||||
memset(_tileSets, 0, 100 * sizeof(TileSet));
|
||||
for (TileSet *t = _tileSets; !in->eos(); ++t) {
|
||||
uint32 off = in->readUint32();
|
||||
if ((off & 0xFFFF) == 0xFFFF)
|
||||
break;
|
||||
t->data = (const uint16*)(tileData + off);
|
||||
t->width = in->readUint16();
|
||||
t->height = in->readUint16();
|
||||
}
|
||||
delete in;
|
||||
|
||||
in = _res->resStreamEndian(3);
|
||||
if (!in)
|
||||
return false;
|
||||
len = in->size();
|
||||
uint8 *frames = new uint8[len];
|
||||
in->read(frames, len);
|
||||
delete in;
|
||||
|
||||
if (id == 53)
|
||||
_vm->delay(2000);
|
||||
else if (id == 55 || id == 56)
|
||||
_vm->snd_playSong(2);
|
||||
|
||||
run(frames);
|
||||
|
||||
delete[] frames;
|
||||
delete[] tileData;
|
||||
if (++id != 54)
|
||||
runLoop = false;
|
||||
}
|
||||
|
||||
debugC(3, kDebugLevelSequence, "Total millis out of sync: %d", _debugResyncCnt);
|
||||
|
||||
if (_vm->shouldQuit() || _vm->skipFlag()) {
|
||||
if (!(_playingID == 55 || _playingID == 56))
|
||||
_vm->snd_stopSound();
|
||||
}
|
||||
|
||||
_vm->_allowSkip = false;
|
||||
_vm->resetSkipFlag();
|
||||
|
||||
_playingID = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::pause(bool togglePause) {
|
||||
if (togglePause)
|
||||
_pauseStart = _vm->_system->getMillis();
|
||||
else
|
||||
_frameTimer += (_vm->_system->getMillis() - _pauseStart);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::run(const uint8 *data) {
|
||||
_waterdeepScene = _playSpeechAnimation = false;
|
||||
_frameTimer = _vm->_system->getMillis();
|
||||
_fastForward = false;
|
||||
|
||||
for (bool runLoop = true; runLoop; ) {
|
||||
// In case of a skip or shouldQuit event we fastforward through the sequence instead of just aborting. This way
|
||||
// we ensure that we have the same palettes and scroll offsets as if the sequence had been played normally.
|
||||
_fastForward = _vm->shouldQuit() || _vm->skipFlag();
|
||||
uint16 frameSize = READ_BE_UINT16(data);
|
||||
if (!frameSize)
|
||||
return;
|
||||
|
||||
uint32 frameStart = _vm->_system->getMillis();
|
||||
uint16 timeStamp = READ_BE_UINT16(data + 2);
|
||||
uint32 nextFrame = _frameTimer + (timeStamp * 16667) / 1000;
|
||||
bool insertDelay = false;
|
||||
|
||||
if (_vm->_system->getMillis() >= nextFrame || _fastForward) {
|
||||
debugC(5, kDebugLevelSequence, "SeqPlayer: Timestamp %08d", timeStamp);
|
||||
for (uint16 timeStamp2 = timeStamp; timeStamp2 == timeStamp; ) {
|
||||
uint16 op = READ_BE_UINT16(data + 4);
|
||||
_opcodes[op]->run(data + 6);
|
||||
_screen->clearPage(0);
|
||||
|
||||
frameSize = READ_BE_UINT16(data);
|
||||
data += (frameSize & ~1);
|
||||
|
||||
timeStamp2 = READ_BE_UINT16(data + 2);
|
||||
}
|
||||
} else {
|
||||
insertDelay = true;
|
||||
}
|
||||
|
||||
if (_waterdeepScene)
|
||||
animateWaterdeepScene();
|
||||
|
||||
if (_playSpeechAnimation)
|
||||
updateSpeechAnimations();
|
||||
|
||||
_animator->update();
|
||||
|
||||
if (_fastForward) {
|
||||
_scrollManager->fastForward();
|
||||
} else {
|
||||
_scrollManager->updateScrollTimers();
|
||||
_renderer->render(0);
|
||||
_screen->sega_updatePaletteFaders(-1);
|
||||
_screen->updateScreen();
|
||||
}
|
||||
|
||||
if (insertDelay) {
|
||||
int diff = _vm->_system->getMillis() - (frameStart + 16);
|
||||
if (diff < 0)
|
||||
_vm->delay((uint32)-diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::animateWaterdeepScene() {
|
||||
if (--_waterdeepSceneTimer > 0)
|
||||
return;
|
||||
_waterdeepSceneTimer = 5;
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
int rnd = _vm->_rnd.getRandomNumber(30);
|
||||
DrawObject *d = &_drawObjects[10 + rnd];
|
||||
_animator->initSprite(_wdAnimSprites[rnd] + 3, _wdDsX[_wdAnimSprites[rnd]] - 80, _wdDsY[_wdAnimSprites[rnd]] + 32, d->nTblVal, d->addr);
|
||||
}
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::updateSpeechAnimations() {
|
||||
if (--_speechAnimTimer > 0)
|
||||
return;
|
||||
|
||||
int animDrawOp = -1;
|
||||
|
||||
for (bool runLoop = true; runLoop; ) {
|
||||
if (_speechAnimTimer == 0) {
|
||||
const uint8 *pos = &_speechAnimData[_speechAnimNo * 12 + _speechAnimFrame];
|
||||
_speechAnimTimer = pos[1];
|
||||
if (pos[0] != 0xFF) {
|
||||
animDrawOp = pos[0];
|
||||
runLoop = false;
|
||||
}
|
||||
_speechAnimFrame += 2;
|
||||
} else {
|
||||
_speechAnimTimer = 0;
|
||||
}
|
||||
|
||||
if (animDrawOp == -1) {
|
||||
_speechAnimNo = (_speechAnimType == 2) ? _vm->_rnd.getRandomNumberRng(4, 6) : _vm->_rnd.getRandomNumberRng(0, 3);
|
||||
_speechAnimFrame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
updateSpeechAnimGraphics(animDrawOp);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::updateSpeechAnimGraphics(int animDrawOp) {
|
||||
assert(animDrawOp < 6);
|
||||
DrawObject *d = &_drawObjects[_speechAnimDrawOps[animDrawOp * 2]];
|
||||
if (_speechAnimDrawOps[animDrawOp * 2 + 1])
|
||||
_renderer->loadToVRAM(d->tileData, (d->width * d->height) << 5, (d->nTblVal & 0x7FF) << 5);
|
||||
else
|
||||
_renderer->fillRectWithTiles(d->addr, d->x, d->y, d->width, d->height, d->nTblVal, true);
|
||||
|
||||
}
|
||||
|
||||
#define ARG(x) READ_BE_UINT16(pos + x)
|
||||
#define S_ARG(x) (int16)ARG(x)
|
||||
|
||||
void SegaSequencePlayer::s_initDrawObject(const uint8 *pos) {
|
||||
int idx = ARG(0);
|
||||
DrawObject *w = &_drawObjects[idx];
|
||||
TileSet *t = &_tileSets[idx];
|
||||
w->agg = ARG(2);
|
||||
w->tileData = t->data;
|
||||
w->width = t->width;
|
||||
w->height = t->height;
|
||||
w->nTblVal = ARG(4) == 0xFFFF ? _drawObjects[idx - 1].width * _drawObjects[idx - 1].height + _drawObjects[idx - 1].nTblVal : (ARG(4) == 0xFFFE ? _drawObjects[idx - 1].nTblVal : ARG(4));
|
||||
w->x = ARG(6);
|
||||
w->y = ARG(8);
|
||||
w->addr = ARG(10);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_drawTileSet(const uint8 *pos) {
|
||||
DrawObject *w = &_drawObjects[ARG(0)];
|
||||
_renderer->fillRectWithTiles(w->addr, w->x, w->y, w->width, w->height, w->nTblVal, true);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_loadTileDataSingle(const uint8 *pos) {
|
||||
DrawObject *w = &_drawObjects[ARG(0)];
|
||||
_renderer->loadToVRAM(w->tileData, (w->width * w-> height) << 5, (w->nTblVal & 0x7FF) << 5);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_drawTileSetCustom(const uint8 *pos) {
|
||||
_renderer->fillRectWithTiles(ARG(8), ARG(0), ARG(2), ARG(4), ARG(6), ARG(10), true);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_drawTileSetCustomTopToBottom(const uint8 *pos) {
|
||||
_renderer->fillRectWithTiles(ARG(8), ARG(0), ARG(2), ARG(4), ARG(6), ARG(10), true, true);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_fillRect(const uint8 *pos) {
|
||||
_renderer->fillRectWithTiles(ARG(8), ARG(0), ARG(2), ARG(4), ARG(6), ARG(10));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_initSprite(const uint8 *pos) {
|
||||
DrawObject *d = &_drawObjects[ARG(2)];
|
||||
_animator->initSprite(ARG(0), d->x << 3, d->y << 3, d->nTblVal, d->addr);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_removeSprite(const uint8 *pos) {
|
||||
_animator->initSprite(ARG(0), 0x4000, 0, 0, 0);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_displayTextJp(const uint8 *pos) {
|
||||
if (_vm->gameFlags().lang != Common::JA_JPN)
|
||||
return;
|
||||
|
||||
const char *str = (const char*)pos;
|
||||
_vm->_txt->clearDim(2);
|
||||
|
||||
int w = _screen->getTextWidth(str);
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
if (w < 288) {
|
||||
x = 152 - (w >> 1);
|
||||
y = 16;
|
||||
}
|
||||
|
||||
_vm->_txt->printShadedText(str, x, y, -1, 0xEE);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_fadeToNeutral(const uint8 *pos) {
|
||||
_screen->sega_fadeToNeutral(ARG(0));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_fadeToBlack(const uint8 *pos) {
|
||||
_screen->sega_fadeToBlack(ARG(0));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_fadeToNeutral2(const uint8 *pos) {
|
||||
_screen->sega_fadeToNeutral(ARG(0));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_fadeToWhite(const uint8 *pos) {
|
||||
_screen->sega_fadeToWhite(ARG(0));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_setPalette(const uint8 *pos) {
|
||||
_screen->sega_selectPalette(ARG(2) + 31, ARG(0), false);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_vScroll(const uint8 *pos) {
|
||||
_scrollManager->setVScrollTimers(ARG(0), S_ARG(2), ARG(4), ARG(6), S_ARG(8), ARG(10));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_hScroll(const uint8 *pos) {
|
||||
_scrollManager->setHScrollTimers(ARG(0), S_ARG(2), ARG(4), ARG(6), S_ARG(8), ARG(10));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_paletteOps(const uint8 *pos) {
|
||||
_screen->sega_paletteOps(S_ARG(0), S_ARG(2), S_ARG(4));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_initSpriteCustomCoords(const uint8 *pos) {
|
||||
DrawObject *d = &_drawObjects[ARG(2)];
|
||||
_animator->initSprite(ARG(0), S_ARG(4), S_ARG(6), d->nTblVal, d->addr);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_fillRectWithPattern(const uint8 *pos) {
|
||||
assert(ARG(12) < 6);
|
||||
_renderer->fillRectWithTiles(ARG(8), ARG(0), ARG(2), ARG(4), ARG(6), ARG(10), false, false, _patternTables[ARG(12)]);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_loadTileDataSeries(const uint8 *pos) {
|
||||
for (DrawObject *d = &_drawObjects[ARG(0)]; d != &_drawObjects[ARG(0) + ARG(2)]; ++d)
|
||||
_renderer->loadToVRAM(d->tileData, (d->width * d->height) << 5, (d->nTblVal & 0x7FF) << 5);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_drawTileSetSeries(const uint8 *pos) {
|
||||
for (DrawObject *d = &_drawObjects[ARG(0)]; d != &_drawObjects[ARG(0) + ARG(2)]; ++d)
|
||||
_renderer->fillRectWithTiles(d->addr, d->x, d->y, d->width, d->height, d->nTblVal, true);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_initSpriteSeries(const uint8 *pos) {
|
||||
int id = ARG(0);
|
||||
for (DrawObject *d = &_drawObjects[ARG(2)]; d != &_drawObjects[ARG(2) + ARG(4)]; ++d)
|
||||
_animator->initSprite(id++, d->x << 3, d->y << 3, d->nTblVal, d->addr);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_initSpriteCustom(const uint8 *pos) {
|
||||
_animator->initSprite(ARG(0), S_ARG(4), S_ARG(6), ARG(2), ARG(8));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_drawTileSetCustomCoords(const uint8 *pos) {
|
||||
DrawObject *w = &_drawObjects[ARG(0)];
|
||||
_renderer->fillRectWithTiles(w->addr, ARG(2), ARG(4), w->width, w->height, w->nTblVal, true);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_waitForPaletteFade(const uint8*) {
|
||||
_screen->sega_fadePalette(0, 0, -1, true, true);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_clearSprites(const uint8*) {
|
||||
_animator->clearSprites();
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_moveSprites2(const uint8 *pos) {
|
||||
_animator->moveSprites2(ARG(0), ARG(2), S_ARG(4), S_ARG(6));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_moveSprites(const uint8 *pos) {
|
||||
_animator->moveSprites(ARG(0), ARG(2), S_ARG(4), S_ARG(6));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_moveMorphSprite(const uint8 *pos) {
|
||||
_animator->moveMorphSprite(ARG(0), ARG(2), S_ARG(4), S_ARG(6));
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_unpauseCD(const uint8 *pos) {
|
||||
// We don't support this in our AudioCD API. The original will use s_playCD() to seek to a track,
|
||||
// wait for the seek to finish and then pause. It then uses this opcode to actually start the playback.
|
||||
// Since s_playCD() and s_unpauseCD() are not always called on the same frame I emulate the original
|
||||
// behavior like this.
|
||||
if (_newTrack != -1)
|
||||
_vm->snd_playSong(_newTrack, false);
|
||||
_newTrack = -1;
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_toggleWaterDeepAnimations(const uint8 *pos) {
|
||||
_waterdeepScene = ARG(0);
|
||||
_waterdeepSceneTimer = 0;
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_assignSpeechAnimGraphics(const uint8 *pos) {
|
||||
if (ARG(0) == 100) {
|
||||
_speechAnimType = ARG(2);
|
||||
} else {
|
||||
assert(ARG(0) < 6);
|
||||
_speechAnimDrawOps[ARG(0) * 2] = ARG(2);
|
||||
_speechAnimDrawOps[ARG(0) * 2 + 1] = ARG(4);
|
||||
}
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_toggleSpeechAnimation(const uint8 *pos) {
|
||||
_playSpeechAnimation = ARG(0);
|
||||
_speechAnimTimer = 0;
|
||||
if (_playSpeechAnimation)
|
||||
updateSpeechAnimGraphics(0);
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_orbZoomEffect(const uint8*) {
|
||||
_renderer->memsetVRAM(0x2AA0, 0, 0x5800);
|
||||
DrawObject *d = &_drawObjects[16];
|
||||
memset(_scaleSrcBuffer, 0, 0x5800);
|
||||
memcpy(_scaleSrcBuffer + 128, d->tileData, (d->width * d->height) << 5);
|
||||
_renderer->fillRectWithTiles(0, 4, 0, 32, 22, 0x2155, true, true);
|
||||
|
||||
memset(_scaleStampMap, 0, 0x100 * sizeof(uint16));
|
||||
uint16 *dst2 = &_scaleStampMap[(7 << 4) + 6];
|
||||
uint16 t = 1;
|
||||
for (int h = 0; h < 9; ++h) {
|
||||
uint16 *dst = dst2;
|
||||
for (int w = 0; w < 10; ++w)
|
||||
*dst++ = t++;
|
||||
dst2 += 16;
|
||||
}
|
||||
|
||||
int step = 512;
|
||||
for (int i = 0; i < 90; ++i) {
|
||||
uint32 nextFrame = _vm->_system->getMillis() + 64;
|
||||
uint16 *dst = _scaleTraceVectors;
|
||||
uint32 xtr = 0x58000 - step * 128;
|
||||
uint32 ytr = 0x59000 - step * 88;
|
||||
for (int ii = 0; ii < 176; ++ii) {
|
||||
*dst++ = xtr >> 8;
|
||||
*dst++ = ytr >> 8;
|
||||
*dst++ = step;
|
||||
*dst++ = 0;
|
||||
ytr += step;
|
||||
}
|
||||
memset(_scaleOutBuffer, 0, 0x5800);
|
||||
_screen->sega_gfxScale(_scaleOutBuffer, 256, 176, 21, _scaleSrcBuffer, _scaleStampMap, _scaleTraceVectors);
|
||||
_renderer->loadToVRAM(_scaleOutBuffer, 0x5800, 0x2AA0);
|
||||
|
||||
if (!_fastForward) {
|
||||
_renderer->render(0);
|
||||
_screen->updateScreen();
|
||||
_vm->delayUntil(nextFrame);
|
||||
}
|
||||
|
||||
step += 16;
|
||||
}
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_stopCD(const uint8*) {
|
||||
_vm->snd_stopSound();
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_playCD(const uint8 *pos) {
|
||||
int track = _cdaTracks[ARG(0)];
|
||||
|
||||
// The original seeks to the requested CD track here and pauses it.
|
||||
// The actual playback is then triggered via s_unpauseCD().
|
||||
if (track)
|
||||
_newTrack = track;
|
||||
_vm->snd_stopSound();
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_displayTextEn(const uint8 *pos) {
|
||||
if (_vm->gameFlags().lang == Common::JA_JPN)
|
||||
return;
|
||||
|
||||
const char *str = (const char*)pos;
|
||||
_vm->_txt->clearDim(2);
|
||||
|
||||
if (_playingID >= 55) {
|
||||
int cs = _screen->setFontStyles(_screen->_currentFont, Font::kStyleFullWidth);
|
||||
_vm->_txt->printShadedText(str, 0, 0, -1, 0xEE);
|
||||
_screen->setFontStyles(_screen->_currentFont, cs);
|
||||
} else {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
if (_playingID >= 53) {
|
||||
x = 152 - (_screen->getTextWidth(str) >> 1);
|
||||
y = 16;
|
||||
}
|
||||
|
||||
_vm->_txt->printShadedText(str, x, y, -1, 0xEE);
|
||||
}
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_loadCustomPalettes(const uint8 *pos) {
|
||||
Common::SeekableReadStreamEndian *in = _res->resStreamEndian(0);
|
||||
in->seek(ARG(0) << 5);
|
||||
_screen->sega_loadCustomPaletteData(in);
|
||||
delete in;
|
||||
}
|
||||
|
||||
void SegaSequencePlayer::s_playSoundEffect(const uint8 *pos) {
|
||||
if (!_fastForward)
|
||||
_vm->snd_playSoundEffect(ARG(0));
|
||||
}
|
||||
|
||||
#undef S_ARG
|
||||
#undef ARG
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif // ENABLE_EOB
|
||||
171
engines/kyra/sequence/seqplayer_eob_segacd.h
Normal file
171
engines/kyra/sequence/seqplayer_eob_segacd.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_EOB
|
||||
|
||||
#ifndef KYRA_SEQPLAYER_SEGACD_H
|
||||
#define KYRA_SEQPLAYER_SEGACD_H
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
class SeekableReadStreamEndian;
|
||||
}
|
||||
|
||||
namespace Kyra {
|
||||
class EoBEngine;
|
||||
class Screen_EoB;
|
||||
class SegaRenderer;
|
||||
class SegaCDResource;
|
||||
class SegaSequencePlayer {
|
||||
public:
|
||||
SegaSequencePlayer(EoBEngine *vm, Screen_EoB *screen, SegaCDResource *res);
|
||||
~SegaSequencePlayer();
|
||||
|
||||
bool play(int id);
|
||||
void pause(bool togglePause);
|
||||
|
||||
private:
|
||||
void run(const uint8 *data);
|
||||
|
||||
void animateWaterdeepScene();
|
||||
void updateSpeechAnimations();
|
||||
void updateSpeechAnimGraphics(int animDrawOp);
|
||||
|
||||
struct TileSet {
|
||||
const uint16 *data;
|
||||
uint16 width;
|
||||
uint16 height;
|
||||
};
|
||||
|
||||
TileSet *_tileSets;
|
||||
|
||||
struct DrawObject {
|
||||
uint16 agg;
|
||||
const uint16 *tileData;
|
||||
uint16 width;
|
||||
uint16 height;
|
||||
uint16 nTblVal;
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
uint16 addr;
|
||||
};
|
||||
|
||||
uint16 _waterdeepScene;
|
||||
uint16 _playSpeechAnimation;
|
||||
uint16 _speechAnimType;
|
||||
uint16 _speechAnimDrawOps[14];
|
||||
uint32 _frameTimer;
|
||||
uint32 _pauseStart;
|
||||
bool _fastForward;
|
||||
|
||||
int _waterdeepSceneTimer, _speechAnimTimer;
|
||||
uint16 _speechAnimNo, _speechAnimFrame;
|
||||
int _playingID;
|
||||
int _newTrack;
|
||||
|
||||
uint8 *_scaleSrcBuffer;
|
||||
uint8 *_scaleOutBuffer;
|
||||
uint16 *_scaleStampMap;
|
||||
uint16 *_scaleTraceVectors;
|
||||
|
||||
uint32 _debugResyncCnt;
|
||||
|
||||
DrawObject *_drawObjects;
|
||||
|
||||
EoBEngine *_vm;
|
||||
Screen_EoB *_screen;
|
||||
SegaRenderer *_renderer;
|
||||
SegaAnimator *_animator;
|
||||
SegaCDResource *_res;
|
||||
ScrollManager *_scrollManager;
|
||||
|
||||
private:
|
||||
class SQOpcode : public Common::Functor1Mem<const uint8*, void, SegaSequencePlayer> {
|
||||
public:
|
||||
typedef Common::Functor1Mem<const uint8*, void, SegaSequencePlayer> SQFunc;
|
||||
SQOpcode(SegaSequencePlayer *sq, const SQFunc::FuncType &func, const char *dbgName) : SQFunc(sq, func), _msg(Common::String::format(" %s()", dbgName)) {}
|
||||
~SQOpcode() override {}
|
||||
void run(const uint8 *arg) {
|
||||
assert(arg);
|
||||
debugC(7, kDebugLevelSequence, "%s", _msg.c_str());
|
||||
if (SQFunc::isValid())
|
||||
SQFunc::operator()(arg);
|
||||
}
|
||||
private:
|
||||
Common::String _msg;
|
||||
};
|
||||
|
||||
Common::Array<SQOpcode*> _opcodes;
|
||||
|
||||
void s_initDrawObject(const uint8 *pos);
|
||||
void s_drawTileSet(const uint8 *pos);
|
||||
void s_loadTileDataSingle(const uint8 *pos);
|
||||
void s_drawTileSetCustom(const uint8 *pos);
|
||||
void s_drawTileSetCustomTopToBottom(const uint8 *pos);
|
||||
void s_fillRect(const uint8 *pos);
|
||||
void s_void(const uint8*) {}
|
||||
void s_initSprite(const uint8 *pos);
|
||||
void s_removeSprite(const uint8 *pos);
|
||||
void s_displayTextJp(const uint8 *pos);
|
||||
void s_fadeToNeutral(const uint8 *pos);
|
||||
void s_fadeToBlack(const uint8 *pos);
|
||||
void s_fadeToNeutral2(const uint8 *pos);
|
||||
void s_fadeToWhite(const uint8 *pos);
|
||||
void s_setPalette(const uint8 *pos);
|
||||
void s_vScroll(const uint8 *pos);
|
||||
void s_hScroll(const uint8 *pos);
|
||||
void s_paletteOps(const uint8 *pos);
|
||||
void s_initSpriteCustomCoords(const uint8 *pos);
|
||||
void s_fillRectWithPattern(const uint8 *pos);
|
||||
void s_loadTileDataSeries(const uint8 *pos);
|
||||
void s_drawTileSetSeries(const uint8 *pos);
|
||||
void s_initSpriteSeries(const uint8 *pos);
|
||||
void s_initSpriteCustom(const uint8 *pos);
|
||||
void s_drawTileSetCustomCoords(const uint8 *pos);
|
||||
void s_waitForPaletteFade(const uint8*);
|
||||
void s_clearSprites(const uint8*);
|
||||
void s_moveSprites2(const uint8 *pos);
|
||||
void s_moveSprites(const uint8 *pos);
|
||||
void s_moveMorphSprite(const uint8 *pos);
|
||||
void s_unpauseCD(const uint8 *pos);
|
||||
void s_toggleWaterDeepAnimations(const uint8 *pos);
|
||||
void s_assignSpeechAnimGraphics(const uint8 *pos);
|
||||
void s_toggleSpeechAnimation(const uint8 *pos);
|
||||
void s_orbZoomEffect(const uint8*);
|
||||
void s_stopCD(const uint8*);
|
||||
void s_playCD(const uint8 *pos);
|
||||
void s_displayTextEn(const uint8 *pos);
|
||||
void s_loadCustomPalettes(const uint8 *pos);
|
||||
void s_playSoundEffect(const uint8 *pos);
|
||||
|
||||
private:
|
||||
const uint8 *_cdaTracks;
|
||||
const uint8 *_wdAnimSprites;
|
||||
const uint8 *_speechAnimData;
|
||||
const uint16 *_wdDsX;
|
||||
const uint8 *_wdDsY;
|
||||
const uint16 *_patternTables[6];
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
#endif // ENABLE_EOB
|
||||
751
engines/kyra/sequence/seqplayer_lok.cpp
Normal file
751
engines/kyra/sequence/seqplayer_lok.cpp
Normal file
@@ -0,0 +1,751 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/sequence/seqplayer_lok.h"
|
||||
#include "kyra/resource/resource.h"
|
||||
#include "kyra/sound/sound.h"
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
SeqPlayer::SeqPlayer(KyraEngine_LoK *vm, OSystem *system) {
|
||||
_vm = vm;
|
||||
_system = system;
|
||||
|
||||
_screen = vm->screen();
|
||||
_sound = vm->sound();
|
||||
_res = vm->resource();
|
||||
|
||||
_copyViewOffs = false;
|
||||
_specialBuffer = nullptr;
|
||||
_seqCode = 0;
|
||||
_seqVocStartTimer = 0;
|
||||
_seqSkipCommand = false;
|
||||
_seqLoopPos = 0;
|
||||
|
||||
_seqData = nullptr;
|
||||
_seqWsaCurDecodePage = 0;
|
||||
_seqDisplayedTextTimer = 0;
|
||||
_seqDisplayTextFlag = false;
|
||||
_seqDisplayedText = 0;
|
||||
_seqDisplayedChar = 0;
|
||||
_seqDisplayedTextX = 0;
|
||||
_seqTalkTextPrinted = false;
|
||||
_seqTalkTextRestored = false;
|
||||
_seqQuitFlag = false;
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(_handShapes); ++i)
|
||||
_handShapes[i] = nullptr;
|
||||
for (int i = 0; i < ARRAYSIZE(_seqMovies); ++i)
|
||||
_seqMovies[i].movie = nullptr;
|
||||
}
|
||||
|
||||
SeqPlayer::~SeqPlayer() {
|
||||
freeHandShapes();
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(_seqMovies); ++i) {
|
||||
if (!_seqMovies[i].movie)
|
||||
continue;
|
||||
_seqMovies[i].movie->close();
|
||||
delete _seqMovies[i].movie;
|
||||
_seqMovies[i].movie = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 *SeqPlayer::setPanPages(int pageNum, int shape) {
|
||||
uint8 *panPage = nullptr;
|
||||
const uint8 *data = _screen->getCPagePtr(pageNum);
|
||||
uint16 numShapes = READ_LE_UINT16(data);
|
||||
if (shape < numShapes) {
|
||||
uint32 offs = 0;
|
||||
if (_vm->gameFlags().useAltShapeHeader)
|
||||
offs = READ_LE_UINT32(data + 2 + shape * 4);
|
||||
else
|
||||
offs = READ_LE_UINT16(data + 2 + shape * 2);
|
||||
|
||||
if (offs != 0) {
|
||||
data += offs;
|
||||
uint16 sz = READ_LE_UINT16(data + 6);
|
||||
panPage = new uint8[sz];
|
||||
assert(panPage);
|
||||
memcpy(panPage, data, sz);
|
||||
}
|
||||
}
|
||||
return panPage;
|
||||
}
|
||||
|
||||
void SeqPlayer::makeHandShapes() {
|
||||
_screen->loadBitmap("WRITING.CPS", 3, 3, &_screen->getPalette(0));
|
||||
if (_vm->gameFlags().platform == Common::kPlatformMacintosh || _vm->gameFlags().platform == Common::kPlatformAmiga) {
|
||||
freeHandShapes();
|
||||
|
||||
int pageBackUp = _screen->_curPage;
|
||||
_screen->_curPage = 2;
|
||||
_handShapes[0] = _screen->encodeShape(0, 0, 88, 122, 0);
|
||||
assert(_handShapes[0]);
|
||||
_handShapes[1] = _screen->encodeShape(88, 0, 80, 117, 0);
|
||||
assert(_handShapes[1]);
|
||||
_handShapes[2] = _screen->encodeShape(168, 0, 117, 124, 0);
|
||||
assert(_handShapes[2]);
|
||||
_screen->_curPage = pageBackUp;
|
||||
} else {
|
||||
for (int i = 0; i < ARRAYSIZE(_handShapes); ++i) {
|
||||
if (_handShapes[i])
|
||||
delete[] _handShapes[i];
|
||||
_handShapes[i] = setPanPages(3, i);
|
||||
assert(_handShapes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::freeHandShapes() {
|
||||
for (int i = 0; i < ARRAYSIZE(_handShapes); ++i) {
|
||||
delete[] _handShapes[i];
|
||||
_handShapes[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_wsaOpen() {
|
||||
uint8 wsaObj = *_seqData++;
|
||||
assert(wsaObj < ARRAYSIZE(_seqMovies));
|
||||
uint8 offscreenDecode = *_seqData++;
|
||||
_seqWsaCurDecodePage = _seqMovies[wsaObj].page = (offscreenDecode == 0) ? 0 : 3;
|
||||
if (!_seqMovies[wsaObj].movie)
|
||||
_seqMovies[wsaObj].movie = _vm->createWSAMovie();
|
||||
_seqMovies[wsaObj].movie->open(_vm->seqWSATable()[wsaObj], offscreenDecode, nullptr);
|
||||
_seqMovies[wsaObj].frame = 0;
|
||||
_seqMovies[wsaObj].numFrames = _seqMovies[wsaObj].movie->frames() - 1;
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_wsaClose() {
|
||||
uint8 wsaObj = *_seqData++;
|
||||
assert(wsaObj < ARRAYSIZE(_seqMovies));
|
||||
if (_seqMovies[wsaObj].movie)
|
||||
_seqMovies[wsaObj].movie->close();
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_wsaPlayFrame() {
|
||||
uint8 wsaObj = *_seqData++;
|
||||
assert(wsaObj < ARRAYSIZE(_seqMovies));
|
||||
int16 frame = (int8)*_seqData++;
|
||||
_seqMovies[wsaObj].pos.x = READ_LE_UINT16(_seqData); _seqData += 2;
|
||||
_seqMovies[wsaObj].pos.y = *_seqData++;
|
||||
assert(_seqMovies[wsaObj].movie);
|
||||
_seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, nullptr, nullptr);
|
||||
_seqMovies[wsaObj].frame = frame;
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_wsaPlayNextFrame() {
|
||||
uint8 wsaObj = *_seqData++;
|
||||
assert(wsaObj < ARRAYSIZE(_seqMovies));
|
||||
int16 frame = ++_seqMovies[wsaObj].frame;
|
||||
if (frame > _seqMovies[wsaObj].numFrames) {
|
||||
frame = 0;
|
||||
_seqMovies[wsaObj].frame = 0;
|
||||
}
|
||||
_seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_wsaPlayPrevFrame() {
|
||||
uint8 wsaObj = *_seqData++;
|
||||
assert(wsaObj < ARRAYSIZE(_seqMovies));
|
||||
int16 frame = --_seqMovies[wsaObj].frame;
|
||||
if (frame < 0) {
|
||||
frame = _seqMovies[wsaObj].numFrames;
|
||||
_seqMovies[wsaObj].frame = frame;
|
||||
} else {
|
||||
_seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_drawShape() {
|
||||
uint8 shapeNum = *_seqData++;
|
||||
int x = READ_LE_UINT16(_seqData); _seqData += 2;
|
||||
int y = *_seqData++;
|
||||
_screen->drawShape(2, _handShapes[shapeNum], x, y, 0, 0, 0);
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_waitTicks() {
|
||||
uint16 ticks = READ_LE_UINT16(_seqData); _seqData += 2;
|
||||
if (_seqCode == 6 && _vm->speechEnabled() && !_vm->textEnabled())
|
||||
return;
|
||||
_vm->delay(ticks * _vm->tickLength());
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_copyWaitTicks() {
|
||||
s1_copyView();
|
||||
s1_waitTicks();
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_shuffleScreen() {
|
||||
_screen->shuffleScreen(0, 16, 320, 128, 2, 0, 0, false);
|
||||
if (_specialBuffer)
|
||||
_screen->copyRegionToBuffer(2, 0, 16, 320, 128, _specialBuffer);
|
||||
_screen->_curPage = 0;
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_copyView() {
|
||||
int h = !_copyViewOffs ? 120 : 128;
|
||||
|
||||
if (_specialBuffer && !_copyViewOffs)
|
||||
_screen->copyToPage0(16, h, 3, _specialBuffer);
|
||||
else
|
||||
_screen->copyRegion(0, 16, 0, 16, 320, h, 2, 0);
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_loopInit() {
|
||||
_seqLoopPos = *_seqData++;
|
||||
if (_seqLoopPos < ARRAYSIZE(_seqLoopTable))
|
||||
_seqLoopTable[_seqLoopPos].ptr = _seqData;
|
||||
else
|
||||
_seqQuitFlag = true;
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_loopInc() {
|
||||
_seqLoopPos = *_seqData++;
|
||||
uint16 seqLoopCount = READ_LE_UINT16(_seqData); _seqData += 2;
|
||||
|
||||
if (_seqCode == 13 && _vm->speechEnabled() && !_vm->textEnabled()) {
|
||||
if (_vm->snd_voiceIsPlaying()) {
|
||||
_seqData = _seqLoopTable[_seqLoopPos].ptr;
|
||||
} else {
|
||||
_seqLoopTable[_seqLoopPos].count = 0xFFFF;
|
||||
_seqLoopTable[_seqLoopPos].ptr = nullptr;
|
||||
}
|
||||
} else if (_seqLoopTable[_seqLoopPos].count == 0xFFFF) {
|
||||
_seqLoopTable[_seqLoopPos].count = seqLoopCount - 1;
|
||||
_seqData = _seqLoopTable[_seqLoopPos].ptr;
|
||||
} else if (_seqLoopTable[_seqLoopPos].count == 0) {
|
||||
_seqLoopTable[_seqLoopPos].count = 0xFFFF;
|
||||
_seqLoopTable[_seqLoopPos].ptr = nullptr;
|
||||
} else {
|
||||
--_seqLoopTable[_seqLoopPos].count;
|
||||
_seqData = _seqLoopTable[_seqLoopPos].ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_skip() {
|
||||
uint8 val = *_seqData++;
|
||||
if (!_vm->speechEnabled() || _vm->textEnabled() || !val)
|
||||
return;
|
||||
|
||||
_seqSkipCommand = true;
|
||||
uint32 vocPlayTime = _vm->snd_getVoicePlayTime();
|
||||
if (vocPlayTime) {
|
||||
if (((_system->getMillis() - _seqVocStartTimer) / _vm->tickLength()) < (val * (vocPlayTime / _vm->tickLength()) / 100))
|
||||
_seqSkipCommand = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_loadPalette() {
|
||||
uint8 colNum = *_seqData++;
|
||||
|
||||
if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
|
||||
if (!colNum)
|
||||
_screen->copyPalette(0, 6);
|
||||
else if (colNum == 3)
|
||||
_screen->copyPalette(0, 7);
|
||||
else if (colNum == 4)
|
||||
_screen->copyPalette(0, 3);
|
||||
|
||||
_screen->setScreenPalette(_screen->getPalette(0));
|
||||
} else {
|
||||
_screen->loadPalette(_vm->seqCOLTable()[colNum], _screen->getPalette(0));
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_loadBitmap() {
|
||||
uint8 cpsNum = *_seqData++;
|
||||
_screen->loadBitmap(_vm->seqCPSTable()[cpsNum], 3, 3, &_screen->getPalette(0));
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_fadeToBlack() {
|
||||
_screen->fadeToBlack();
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_printText() {
|
||||
static const uint8 colorMap[] = { 0, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0 };
|
||||
uint8 txt = *_seqData++;
|
||||
|
||||
if (!_vm->textEnabled())
|
||||
return;
|
||||
|
||||
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
|
||||
_screen->fillRect(0, 180, 319, 195, 0);
|
||||
else
|
||||
_screen->fillRect(0, 180, 319, 195, 12);
|
||||
_screen->setTextColorMap(colorMap);
|
||||
if (!_seqDisplayTextFlag) {
|
||||
const char *str = _vm->seqTextsTable()[txt];
|
||||
int x = (Screen::SCREEN_W - _screen->getTextWidth(str)) / 2;
|
||||
_screen->printText(str, x, 180, 0xF, 0xC);
|
||||
} else {
|
||||
_seqDisplayedTextTimer = _system->getMillis() + 1000 / ((_vm->gameFlags().lang == Common::FR_FRA) ? 120 : 60);
|
||||
_seqDisplayedText = txt;
|
||||
_seqDisplayedChar = 0;
|
||||
const char *str = _vm->seqTextsTable()[_seqDisplayedText];
|
||||
_seqDisplayedTextX = (Screen::SCREEN_W - _screen->getTextWidth(str)) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_printTalkText() {
|
||||
uint8 txt = *_seqData++;
|
||||
int x = READ_LE_UINT16(_seqData); _seqData += 2;
|
||||
int y = *_seqData++;
|
||||
uint8 fillColor = *_seqData++;
|
||||
|
||||
int b;
|
||||
if (_seqTalkTextPrinted && !_seqTalkTextRestored) {
|
||||
if (_seqWsaCurDecodePage != 0 && !_specialBuffer)
|
||||
b = 2;
|
||||
else
|
||||
b = 0;
|
||||
_vm->text()->restoreTalkTextMessageBkgd(2, b);
|
||||
}
|
||||
|
||||
if (!_vm->textEnabled())
|
||||
return;
|
||||
|
||||
_seqTalkTextPrinted = true;
|
||||
_seqTalkTextRestored = false;
|
||||
if (_seqWsaCurDecodePage != 0 && !_specialBuffer)
|
||||
b = 2;
|
||||
else
|
||||
b = 0;
|
||||
_vm->text()->printTalkTextMessage(_vm->seqTextsTable()[txt], x, y, fillColor, b, 2);
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_restoreTalkText() {
|
||||
if (_seqTalkTextPrinted && !_seqTalkTextRestored && _vm->textEnabled()) {
|
||||
int b;
|
||||
if (_seqWsaCurDecodePage != 0 && !_specialBuffer)
|
||||
b = 2;
|
||||
else
|
||||
b = 0;
|
||||
_vm->text()->restoreTalkTextMessageBkgd(2, b);
|
||||
_seqTalkTextRestored = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_clearCurrentScreen() {
|
||||
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
|
||||
_screen->fillRect(10, 180, 319, 195, 0);
|
||||
else
|
||||
_screen->fillRect(10, 180, 319, 196, 0xC);
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_break() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_fadeFromBlack() {
|
||||
_screen->fadeFromBlack();
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_copyRegion() {
|
||||
uint8 srcPage = *_seqData++;
|
||||
uint8 dstPage = *_seqData++;
|
||||
_screen->copyRegion(0, 0, 0, 0, 320, 200, srcPage, dstPage);
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_copyRegionSpecial() {
|
||||
static const uint8 colorMap[] = { 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0 };
|
||||
const char *copyStr = nullptr;
|
||||
if (!_vm->gameFlags().isTalkie)
|
||||
copyStr = "Copyright (c) 1992 Westwood Studios";
|
||||
else
|
||||
copyStr = "Copyright (c) 1992,1993 Westwood Studios";
|
||||
|
||||
uint8 so = *_seqData++;
|
||||
switch (so) {
|
||||
case 0:
|
||||
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
|
||||
_screen->copyRegion(0, 0, 0, 47, 312, 76, 2, 0);
|
||||
else
|
||||
_screen->copyRegion(0, 0, 0, 47, 320, 77, 2, 0);
|
||||
break;
|
||||
case 1:
|
||||
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
|
||||
_screen->copyRegion(0, 0, 8, 47, 312, 55, 2, 0);
|
||||
else
|
||||
_screen->copyRegion(0, 0, 0, 47, 320, 56, 2, 0);
|
||||
break;
|
||||
case 2:
|
||||
if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
|
||||
_screen->copyRegion(104, 72, 104, 72, 40, 87, 2, 0);
|
||||
_screen->copyRegion(128, 159, 128, 159, 32, 17, 2, 0);
|
||||
_screen->copyRegion(160, 105, 160, 105, 32, 9, 2, 0);
|
||||
_screen->copyRegion(200, 83, 200, 83, 88, 93, 2, 0);
|
||||
} else {
|
||||
_screen->copyRegion(107, 72, 107, 72, 43, 87, 2, 0);
|
||||
_screen->copyRegion(130, 159, 130, 159, 35, 17, 2, 0);
|
||||
_screen->copyRegion(165, 105, 165, 105, 32, 9, 2, 0);
|
||||
_screen->copyRegion(206, 83, 206, 83, 94, 93, 2, 0);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
_screen->copyRegion(152, 56, 152, 56, 48, 48, 2, 0);
|
||||
break;
|
||||
case 4: {
|
||||
_screen->_charSpacing = -2;
|
||||
const int x = (Screen::SCREEN_W - _screen->getTextWidth(copyStr)) / 2;
|
||||
const int y = 179;
|
||||
_screen->setTextColorMap(colorMap);
|
||||
if (_vm->gameFlags().platform != Common::kPlatformAmiga)
|
||||
_screen->printText(copyStr, x + 1, y + 1, 0xB, 0xC);
|
||||
_screen->printText(copyStr, x, y, 0xF, 0xC);
|
||||
} break;
|
||||
case 5:
|
||||
_screen->_curPage = 2;
|
||||
break;
|
||||
default:
|
||||
error("Invalid subopcode %d for s1_copyRegionSpecial", so);
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_fillRect() {
|
||||
int x1 = READ_LE_UINT16(_seqData); _seqData += 2;
|
||||
int y1 = *_seqData++;
|
||||
int x2 = READ_LE_UINT16(_seqData); _seqData += 2;
|
||||
int y2 = *_seqData++;
|
||||
uint8 color = *_seqData++;
|
||||
uint8 page = *_seqData++;
|
||||
_screen->fillRect(x1, y1, x2, y2, color, page);
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_playEffect() {
|
||||
uint8 track = *_seqData++;
|
||||
_vm->delay(3 * _vm->tickLength());
|
||||
|
||||
if (_vm->gameFlags().platform == Common::kPlatformPC98) {
|
||||
if (track > 21 && track < 38)
|
||||
track -= 22;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
_sound->playSoundEffect(track);
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_playTrack() {
|
||||
uint8 msg = *_seqData++;
|
||||
|
||||
if (_vm->gameFlags().platform != Common::kPlatformMacintosh && _vm->gameFlags().platform != Common::kPlatformAmiga)
|
||||
_vm->delay(3 * _vm->tickLength());
|
||||
|
||||
if (msg == 0 && (_vm->gameFlags().platform != Common::kPlatformDOS && _vm->gameFlags().platform != Common::kPlatformAmiga)) {
|
||||
_sound->haltTrack();
|
||||
} else if (msg == 1) {
|
||||
_sound->beginFadeOut();
|
||||
} else {
|
||||
_sound->haltTrack();
|
||||
if (_vm->gameFlags().platform != Common::kPlatformMacintosh && _vm->gameFlags().platform != Common::kPlatformAmiga)
|
||||
_vm->delay(3 * _vm->tickLength());
|
||||
_sound->playTrack(_vm->gameFlags().platform == Common::kPlatformFMTowns ? msg + 2 : msg);
|
||||
}
|
||||
|
||||
if (msg < 2 && (_vm->gameFlags().platform != Common::kPlatformMacintosh && _vm->gameFlags().platform != Common::kPlatformAmiga))
|
||||
_vm->delay(3 * _vm->tickLength());
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_allocTempBuffer() {
|
||||
if (_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie) {
|
||||
_seqQuitFlag = true;
|
||||
} else {
|
||||
if (!_specialBuffer && !_copyViewOffs) {
|
||||
_specialBuffer = new uint8[40960];
|
||||
assert(_specialBuffer);
|
||||
_screen->copyRegionToBuffer(2, 0, 16, 320, 128, _specialBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_textDisplayEnable() {
|
||||
_seqDisplayTextFlag = true;
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_textDisplayDisable() {
|
||||
_seqDisplayTextFlag = false;
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_endOfScript() {
|
||||
_seqQuitFlag = true;
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_loadIntroVRM() {
|
||||
_res->loadPakFile("INTRO.VRM");
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_playVocFile() {
|
||||
_vm->snd_voiceWaitForFinish(false);
|
||||
uint8 a = *_seqData++;
|
||||
if (_vm->speechEnabled()) {
|
||||
_seqVocStartTimer = _system->getMillis();
|
||||
_vm->snd_playVoiceFile(a);
|
||||
}
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_miscUnk3() {
|
||||
// This is just a file cash flushing function in the original. We don't need that.
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_prefetchVocFile() {
|
||||
_seqData++;
|
||||
// we do not have to prefetch the vocfiles on modern systems
|
||||
}
|
||||
|
||||
void SeqPlayer::s1_textDisplayWait() {
|
||||
// This is used in the Mac Talkie version for the Kallak writing sequence.
|
||||
// But in my tests the condition was never reached...
|
||||
if (_seqDisplayedTextTimer != 0xFFFFFFFF)
|
||||
_seqData--;
|
||||
}
|
||||
|
||||
#define SEQOP(n, x) { n, &SeqPlayer::x, #x }
|
||||
|
||||
bool SeqPlayer::playSequence(const uint8 *seqData, bool skipSeq) {
|
||||
assert(seqData);
|
||||
|
||||
static const SeqEntry floppySeqProcs[] = {
|
||||
// 0x00
|
||||
SEQOP(3, s1_wsaOpen),
|
||||
SEQOP(2, s1_wsaClose),
|
||||
SEQOP(6, s1_wsaPlayFrame),
|
||||
SEQOP(2, s1_wsaPlayNextFrame),
|
||||
// 0x04
|
||||
SEQOP(2, s1_wsaPlayPrevFrame),
|
||||
SEQOP(5, s1_drawShape),
|
||||
SEQOP(3, s1_waitTicks),
|
||||
SEQOP(3, s1_copyWaitTicks),
|
||||
// 0x08
|
||||
SEQOP(1, s1_shuffleScreen),
|
||||
SEQOP(1, s1_copyView),
|
||||
SEQOP(2, s1_loopInit),
|
||||
SEQOP(4, s1_loopInc),
|
||||
// 0x0C
|
||||
SEQOP(2, s1_loadPalette),
|
||||
SEQOP(2, s1_loadBitmap),
|
||||
SEQOP(1, s1_fadeToBlack),
|
||||
SEQOP(2, s1_printText),
|
||||
// 0x10
|
||||
SEQOP(6, s1_printTalkText),
|
||||
SEQOP(1, s1_restoreTalkText),
|
||||
SEQOP(1, s1_clearCurrentScreen),
|
||||
SEQOP(1, s1_break),
|
||||
// 0x14
|
||||
SEQOP(1, s1_fadeFromBlack),
|
||||
SEQOP(3, s1_copyRegion),
|
||||
SEQOP(2, s1_copyRegionSpecial),
|
||||
SEQOP(9, s1_fillRect),
|
||||
// 0x18
|
||||
SEQOP(2, s1_playEffect),
|
||||
SEQOP(2, s1_playTrack),
|
||||
SEQOP(1, s1_allocTempBuffer),
|
||||
SEQOP(1, s1_textDisplayEnable),
|
||||
// 0x1C
|
||||
SEQOP(1, s1_textDisplayDisable),
|
||||
SEQOP(1, s1_endOfScript)
|
||||
};
|
||||
|
||||
static const SeqEntry cdromSeqProcs[] = {
|
||||
// 0x00
|
||||
SEQOP(3, s1_wsaOpen),
|
||||
SEQOP(2, s1_wsaClose),
|
||||
SEQOP(6, s1_wsaPlayFrame),
|
||||
SEQOP(2, s1_wsaPlayNextFrame),
|
||||
// 0x04
|
||||
SEQOP(2, s1_wsaPlayPrevFrame),
|
||||
SEQOP(5, s1_drawShape),
|
||||
SEQOP(3, s1_waitTicks),
|
||||
SEQOP(3, s1_waitTicks),
|
||||
// 0x08
|
||||
SEQOP(3, s1_copyWaitTicks),
|
||||
SEQOP(1, s1_shuffleScreen),
|
||||
SEQOP(1, s1_copyView),
|
||||
SEQOP(2, s1_loopInit),
|
||||
// 0x0C
|
||||
SEQOP(4, s1_loopInc),
|
||||
SEQOP(4, s1_loopInc),
|
||||
SEQOP(2, s1_skip),
|
||||
SEQOP(2, s1_loadPalette),
|
||||
// 0x10
|
||||
SEQOP(2, s1_loadBitmap),
|
||||
SEQOP(1, s1_fadeToBlack),
|
||||
SEQOP(2, s1_printText),
|
||||
SEQOP(6, s1_printTalkText),
|
||||
// 0x14
|
||||
SEQOP(1, s1_restoreTalkText),
|
||||
SEQOP(1, s1_clearCurrentScreen),
|
||||
SEQOP(1, s1_break),
|
||||
SEQOP(1, s1_fadeFromBlack),
|
||||
// 0x18
|
||||
SEQOP(3, s1_copyRegion),
|
||||
SEQOP(2, s1_copyRegionSpecial),
|
||||
SEQOP(9, s1_fillRect),
|
||||
SEQOP(2, s1_playEffect),
|
||||
// 0x1C
|
||||
SEQOP(2, s1_playTrack),
|
||||
SEQOP(1, s1_allocTempBuffer),
|
||||
SEQOP(1, s1_textDisplayEnable),
|
||||
SEQOP(1, s1_textDisplayDisable),
|
||||
// 0x20
|
||||
SEQOP(1, s1_endOfScript),
|
||||
SEQOP(1, s1_loadIntroVRM),
|
||||
SEQOP(2, s1_playVocFile),
|
||||
SEQOP(1, s1_miscUnk3),
|
||||
// 0x24
|
||||
SEQOP(2, s1_prefetchVocFile),
|
||||
SEQOP(1, s1_textDisplayWait)
|
||||
};
|
||||
|
||||
const SeqEntry *commands;
|
||||
int numCommands;
|
||||
|
||||
if (_vm->gameFlags().isTalkie) {
|
||||
commands = cdromSeqProcs;
|
||||
numCommands = ARRAYSIZE(cdromSeqProcs);
|
||||
} else {
|
||||
commands = floppySeqProcs;
|
||||
numCommands = ARRAYSIZE(floppySeqProcs);
|
||||
}
|
||||
|
||||
bool seqSkippedFlag = false;
|
||||
|
||||
_seqData = seqData;
|
||||
|
||||
_seqDisplayedTextTimer = 0xFFFFFFFF;
|
||||
_seqDisplayTextFlag = false;
|
||||
_seqDisplayedTextX = 0;
|
||||
_seqDisplayedText = 0;
|
||||
_seqDisplayedChar = 0;
|
||||
_seqTalkTextRestored = false;
|
||||
_seqTalkTextPrinted = false;
|
||||
_seqSkipCommand = false;
|
||||
|
||||
_seqQuitFlag = false;
|
||||
_seqWsaCurDecodePage = 0;
|
||||
_seqLoopPos = 0;
|
||||
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
_seqLoopTable[i].ptr = nullptr;
|
||||
_seqLoopTable[i].count = 0xFFFF;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE(_seqMovies); i++) {
|
||||
_seqMovies[i].clear();
|
||||
}
|
||||
|
||||
_screen->_curPage = 0;
|
||||
char revBuffer[384];
|
||||
memset(revBuffer, 0, sizeof(revBuffer));
|
||||
int charIdx = 0;
|
||||
while (!_seqQuitFlag && !_vm->shouldQuit()) {
|
||||
uint32 startFrameCt = _vm->_system->getMillis();
|
||||
if (_seqSkipCommand || (skipSeq && _vm->seq_skipSequence())) {
|
||||
while (1) {
|
||||
uint8 code = *_seqData;
|
||||
if (commands[code].proc == &SeqPlayer::s1_endOfScript)
|
||||
break;
|
||||
if (_seqSkipCommand && commands[code].proc == &SeqPlayer::s1_skip && _seqData[1] == 0)
|
||||
break;
|
||||
if (commands[code].proc == &SeqPlayer::s1_break)
|
||||
break;
|
||||
|
||||
_seqData += commands[code].len;
|
||||
}
|
||||
skipSeq = false;
|
||||
seqSkippedFlag = true;
|
||||
|
||||
if (_seqSkipCommand) {
|
||||
_seqSkipCommand = false;
|
||||
_seqData += commands[14].len;
|
||||
_seqLoopTable[_seqLoopPos].count = 0xFFFF;
|
||||
_seqLoopTable[_seqLoopPos].ptr = nullptr;
|
||||
}
|
||||
}
|
||||
// used in Kallak writing intro
|
||||
if (_seqDisplayTextFlag && _seqDisplayedTextTimer != 0xFFFFFFFF && _vm->textEnabled()) {
|
||||
if (_seqDisplayedTextTimer < _system->getMillis()) {
|
||||
char charStr[3];
|
||||
charStr[0] = _vm->seqTextsTable()[_seqDisplayedText][_seqDisplayedChar];
|
||||
if (_vm->gameFlags().lang == Common::HE_ISR) {
|
||||
for (int k = charIdx; k > 0; k--) {
|
||||
revBuffer[k] = revBuffer[k - 1];
|
||||
}
|
||||
revBuffer[0] = charStr[0];
|
||||
if (!charIdx) {
|
||||
int w = _screen->getTextWidth(_vm->seqTextsTable()[_seqDisplayedText] + _seqDisplayedChar);
|
||||
_seqDisplayedTextX += w;
|
||||
}
|
||||
charIdx++;
|
||||
}
|
||||
charStr[1] = charStr[2] = '\0';
|
||||
if (_vm->gameFlags().lang == Common::JA_JPN || _vm->gameFlags().lang == Common::ZH_TWN || (_vm->gameFlags().lang == Common::KO_KOR && (charStr[0] & 0x80))) {
|
||||
charStr[1] = _vm->seqTextsTable()[_seqDisplayedText][++_seqDisplayedChar];
|
||||
_screen->printText(charStr, _seqDisplayedTextX, 180, 0xF, 0xC);
|
||||
_seqDisplayedTextX += _screen->getTextWidth(charStr);
|
||||
} else if (_vm->gameFlags().lang == Common::HE_ISR) {
|
||||
_seqDisplayedTextX -= _screen->getCharWidth((uint8)charStr[0]);
|
||||
_screen->printText(revBuffer, _seqDisplayedTextX, 180, 0xF, 0xC);
|
||||
} else {
|
||||
_screen->printText(charStr, _seqDisplayedTextX, 180, 0xF, 0xC);
|
||||
_seqDisplayedTextX += _screen->getCharWidth((uint8)charStr[0]);
|
||||
}
|
||||
++_seqDisplayedChar;
|
||||
|
||||
if (_vm->seqTextsTable()[_seqDisplayedText][_seqDisplayedChar] == '\0') {
|
||||
_seqDisplayedTextTimer = 0xFFFFFFFF;
|
||||
memset(revBuffer, 0, sizeof(revBuffer));
|
||||
charIdx = 0;
|
||||
} else {
|
||||
_seqDisplayedTextTimer = _system->getMillis() + 1000 / ((_vm->gameFlags().lang == Common::FR_FRA) ? 120 : 60);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_seqCode = *_seqData++;
|
||||
if (_seqCode < numCommands) {
|
||||
SeqProc currentProc = commands[_seqCode].proc;
|
||||
debugC(5, kDebugLevelSequence, "0x%.4X seqCode = %d (%s)", (uint16)(_seqData - 1 - seqData), _seqCode, commands[_seqCode].desc);
|
||||
(this->*currentProc)();
|
||||
} else {
|
||||
error("Invalid sequence opcode %d called from 0x%.04X", _seqCode, (uint16)(_seqData - 1 - seqData));
|
||||
}
|
||||
|
||||
int extraDelay = _screen->updateScreen();
|
||||
uint32 ct = _system->getMillis();
|
||||
_vm->delayUntil(startFrameCt + extraDelay > ct ? startFrameCt + extraDelay : ct + 8);
|
||||
}
|
||||
delete[] _specialBuffer;
|
||||
_specialBuffer = nullptr;
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE(_seqMovies); ++i) {
|
||||
delete _seqMovies[i].movie;
|
||||
_seqMovies[i].movie = nullptr;
|
||||
}
|
||||
return seqSkippedFlag;
|
||||
}
|
||||
|
||||
#undef SEQOP
|
||||
#undef KYRA_SEQ_SCREENFRAMEDELAY_MIN
|
||||
|
||||
} // End of namespace Kyra
|
||||
137
engines/kyra/sequence/seqplayer_lok.h
Normal file
137
engines/kyra/sequence/seqplayer_lok.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_SEQPLAYER_H
|
||||
#define KYRA_SEQPLAYER_H
|
||||
|
||||
#include "kyra/engine/kyra_lok.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
class SeqPlayer {
|
||||
public:
|
||||
SeqPlayer(KyraEngine_LoK *vm, OSystem *system);
|
||||
~SeqPlayer();
|
||||
|
||||
void setCopyViewOffs(bool offs) {
|
||||
_copyViewOffs = offs;
|
||||
}
|
||||
|
||||
void makeHandShapes();
|
||||
void freeHandShapes();
|
||||
|
||||
bool playSequence(const uint8 *seqData, bool skipSeq);
|
||||
|
||||
uint8 *setPanPages(int pageNum, int shape);
|
||||
protected:
|
||||
KyraEngine_LoK *_vm;
|
||||
OSystem *_system;
|
||||
Screen *_screen;
|
||||
Sound *_sound;
|
||||
Resource *_res;
|
||||
|
||||
uint8 *_handShapes[3];
|
||||
bool _copyViewOffs;
|
||||
|
||||
typedef void (SeqPlayer::*SeqProc)();
|
||||
struct SeqEntry {
|
||||
uint8 len;
|
||||
SeqProc proc;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
// the sequence procs
|
||||
void s1_wsaOpen();
|
||||
void s1_wsaClose();
|
||||
void s1_wsaPlayFrame();
|
||||
void s1_wsaPlayNextFrame();
|
||||
void s1_wsaPlayPrevFrame();
|
||||
void s1_drawShape();
|
||||
void s1_waitTicks();
|
||||
void s1_copyWaitTicks();
|
||||
void s1_shuffleScreen();
|
||||
void s1_copyView();
|
||||
void s1_loopInit();
|
||||
void s1_loopInc();
|
||||
void s1_skip();
|
||||
void s1_loadPalette();
|
||||
void s1_loadBitmap();
|
||||
void s1_fadeToBlack();
|
||||
void s1_printText();
|
||||
void s1_printTalkText();
|
||||
void s1_restoreTalkText();
|
||||
void s1_clearCurrentScreen();
|
||||
void s1_break();
|
||||
void s1_fadeFromBlack();
|
||||
void s1_copyRegion();
|
||||
void s1_copyRegionSpecial();
|
||||
void s1_fillRect();
|
||||
void s1_playEffect();
|
||||
void s1_playTrack();
|
||||
void s1_allocTempBuffer();
|
||||
void s1_textDisplayEnable();
|
||||
void s1_textDisplayDisable();
|
||||
void s1_endOfScript();
|
||||
void s1_loadIntroVRM();
|
||||
void s1_playVocFile();
|
||||
void s1_miscUnk3();
|
||||
void s1_prefetchVocFile();
|
||||
void s1_textDisplayWait();
|
||||
|
||||
struct SeqMovie {
|
||||
Movie *movie;
|
||||
int32 page;
|
||||
int16 frame;
|
||||
int16 numFrames;
|
||||
Common::Point pos;
|
||||
|
||||
void clear() {
|
||||
movie = nullptr;
|
||||
page = 0;
|
||||
frame = 0;
|
||||
numFrames = 0;
|
||||
pos.x = 0;
|
||||
pos.y = 0;
|
||||
}
|
||||
};
|
||||
|
||||
const uint8 *_seqData;
|
||||
uint8 _seqCode;
|
||||
uint8 *_specialBuffer;
|
||||
SeqMovie _seqMovies[12];
|
||||
SeqLoop _seqLoopTable[20];
|
||||
uint8 _seqLoopPos;
|
||||
uint16 _seqWsaCurDecodePage;
|
||||
uint32 _seqDisplayedTextTimer;
|
||||
uint32 _seqVocStartTimer;
|
||||
bool _seqDisplayTextFlag;
|
||||
uint8 _seqDisplayedText;
|
||||
uint8 _seqDisplayedChar;
|
||||
uint16 _seqDisplayedTextX;
|
||||
bool _seqTalkTextPrinted;
|
||||
bool _seqTalkTextRestored;
|
||||
bool _seqQuitFlag;
|
||||
bool _seqSkipCommand;
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
2025
engines/kyra/sequence/sequences_darkmoon.cpp
Normal file
2025
engines/kyra/sequence/sequences_darkmoon.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2855
engines/kyra/sequence/sequences_eob.cpp
Normal file
2855
engines/kyra/sequence/sequences_eob.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3641
engines/kyra/sequence/sequences_hof.cpp
Normal file
3641
engines/kyra/sequence/sequences_hof.cpp
Normal file
File diff suppressed because it is too large
Load Diff
73
engines/kyra/sequence/sequences_hof.h
Normal file
73
engines/kyra/sequence/sequences_hof.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_SEQUENCES_HOF_H
|
||||
#define KYRA_SEQUENCES_HOF_H
|
||||
|
||||
#include "kyra/engine/kyra_v2.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
struct HoFSequence {
|
||||
const char *wsaFile;
|
||||
const char *cpsFile;
|
||||
uint16 flags;
|
||||
uint8 fadeInTransitionType;
|
||||
uint8 fadeOutTransitionType;
|
||||
int16 stringIndex1;
|
||||
int16 stringIndex2;
|
||||
uint16 startFrame;
|
||||
uint16 numFrames;
|
||||
uint16 duration;
|
||||
uint16 xPos;
|
||||
uint16 yPos;
|
||||
uint16 timeout;
|
||||
};
|
||||
|
||||
struct HoFNestedSequence {
|
||||
const char *wsaFile;
|
||||
const FrameControl *wsaControl;
|
||||
uint16 flags;
|
||||
uint16 startframe;
|
||||
uint16 endFrame;
|
||||
uint16 frameDelay;
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
uint16 fadeInTransitionType;
|
||||
uint16 fadeOutTransitionType;
|
||||
};
|
||||
|
||||
struct HoFSeqData {
|
||||
const HoFSequence *seq;
|
||||
int numSeq;
|
||||
const HoFNestedSequence *nestedSeq;
|
||||
int numNestedSeq;
|
||||
};
|
||||
|
||||
struct HoFSeqItemAnimData {
|
||||
int16 itemIndex;
|
||||
uint16 y;
|
||||
const uint16 *frames;
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
2162
engines/kyra/sequence/sequences_lok.cpp
Normal file
2162
engines/kyra/sequence/sequences_lok.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1572
engines/kyra/sequence/sequences_lol.cpp
Normal file
1572
engines/kyra/sequence/sequences_lol.cpp
Normal file
File diff suppressed because it is too large
Load Diff
237
engines/kyra/sequence/sequences_mr.cpp
Normal file
237
engines/kyra/sequence/sequences_mr.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/engine/kyra_mr.h"
|
||||
#include "kyra/resource/resource.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
void KyraEngine_MR::showBadConscience() {
|
||||
if (_badConscienceShown)
|
||||
return;
|
||||
|
||||
_badConscienceShown = true;
|
||||
_badConscienceAnim = _rnd.getRandomNumberRng(0, 2);
|
||||
if (_currentChapter == 2)
|
||||
_badConscienceAnim = 5;
|
||||
else if (_currentChapter == 3)
|
||||
_badConscienceAnim = 3;
|
||||
else if (_currentChapter == 4 && _rnd.getRandomNumberRng(1, 100) <= 25)
|
||||
_badConscienceAnim = 6;
|
||||
else if (_currentChapter == 5 && _rnd.getRandomNumberRng(1, 100) <= 25)
|
||||
_badConscienceAnim = 7;
|
||||
|
||||
if (_characterShapeFile == 9)
|
||||
_badConscienceAnim = 4;
|
||||
|
||||
_badConsciencePosition = (_mainCharacter.x1 <= 160);
|
||||
|
||||
if (_goodConscienceShown)
|
||||
_badConsciencePosition = !_goodConsciencePosition;
|
||||
|
||||
int anim = _badConscienceAnim + (_badConsciencePosition ? 0 : 8);
|
||||
TalkObject &talkObject = _talkObjectList[1];
|
||||
|
||||
if (_badConsciencePosition)
|
||||
talkObject.x = 290;
|
||||
else
|
||||
talkObject.x = 30;
|
||||
talkObject.y = 30;
|
||||
|
||||
static const char *const animFilenames[] = {
|
||||
"GUNFL00.WSA", "GUNFL01.WSA", "GUNFL02.WSA", "GUNFL03.WSA", "GUNFL04.WSA", "GUNFL05.WSA", "GUNFL06.WSA", "GUNFL07.WSA",
|
||||
"GUNFR00.WSA", "GUNFR01.WSA", "GUNFR02.WSA", "GUNFR03.WSA", "GUNFR04.WSA", "GUNFR05.WSA", "GUNFR06.WSA", "GUNFR07.WSA"
|
||||
};
|
||||
|
||||
setupSceneAnimObject(0x0E, 9, 0, _interfaceCommandLineY1 - 1, -1, -1, -1, -1, 0, 0, 0, -1, animFilenames[anim]);
|
||||
for (uint i = 0; i <= _badConscienceFrameTable[_badConscienceAnim]; ++i) {
|
||||
if (i == 8)
|
||||
snd_playSoundEffect(0x1B, 0xC8);
|
||||
updateSceneAnim(0x0E, i);
|
||||
delay(3*_tickLength, true);
|
||||
}
|
||||
|
||||
if (_mainCharacter.animFrame < 50 || _mainCharacter.animFrame > 87)
|
||||
return;
|
||||
|
||||
if (_mainCharacter.y1 == -1 || (_mainCharacter.x1 != -1 && _mainCharacter.animFrame == 87) || _mainCharacter.animFrame == 87) {
|
||||
_mainCharacter.animFrame = 87;
|
||||
} else {
|
||||
if (_badConsciencePosition)
|
||||
_mainCharacter.facing = 3;
|
||||
else
|
||||
_mainCharacter.facing = 5;
|
||||
// _mainCharacter.facing can not be 0xFF here, so this is safe.
|
||||
_mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
|
||||
}
|
||||
|
||||
updateCharacterAnim(0);
|
||||
refreshAnimObjectsIfNeed();
|
||||
}
|
||||
|
||||
void KyraEngine_MR::hideBadConscience() {
|
||||
if (!_badConscienceShown)
|
||||
return;
|
||||
|
||||
_badConscienceShown = false;
|
||||
for (int frame = _badConscienceFrameTable[_badConscienceAnim+8]; frame >= 0; --frame) {
|
||||
if (frame == 15)
|
||||
snd_playSoundEffect(0x31, 0xC8);
|
||||
updateSceneAnim(0x0E, frame);
|
||||
delay(1*_tickLength, true);
|
||||
}
|
||||
|
||||
updateSceneAnim(0x0E, -1);
|
||||
update();
|
||||
removeSceneAnimObject(0x0E, 1);
|
||||
setNextIdleAnimTimer();
|
||||
}
|
||||
|
||||
void KyraEngine_MR::showGoodConscience() {
|
||||
if (_goodConscienceShown)
|
||||
return;
|
||||
|
||||
_goodConscienceShown = true;
|
||||
++_goodConscienceAnim;
|
||||
_goodConscienceAnim %= 5;
|
||||
|
||||
setNextIdleAnimTimer();
|
||||
_goodConsciencePosition = (_mainCharacter.x1 <= 160);
|
||||
|
||||
if (_badConscienceShown)
|
||||
_goodConsciencePosition = !_badConsciencePosition;
|
||||
|
||||
int anim = _goodConscienceAnim + (_goodConsciencePosition ? 0 : 5);
|
||||
TalkObject &talkObject = _talkObjectList[87];
|
||||
|
||||
if (_goodConsciencePosition)
|
||||
talkObject.x = 290;
|
||||
else
|
||||
talkObject.x = 30;
|
||||
talkObject.y = 30;
|
||||
|
||||
static const char *const animFilenames[] = {
|
||||
"STUFL00.WSA", "STUFL02.WSA", "STUFL04.WSA", "STUFL03.WSA", "STUFL01.WSA",
|
||||
"STUFR00.WSA", "STUFR02.WSA", "STUFR04.WSA", "STUFR03.WSA", "STUFR01.WSA"
|
||||
};
|
||||
|
||||
setupSceneAnimObject(0x0F, 9, 0, 187, -1, -1, -1, -1, 0, 0, 0, -1, animFilenames[anim]);
|
||||
for (uint i = 0; i <= _goodConscienceFrameTable[_goodConscienceAnim]; ++i) {
|
||||
if (i == 10)
|
||||
snd_playSoundEffect(0x7F, 0xC8);
|
||||
updateSceneAnim(0x0F, i);
|
||||
delay(2*_tickLength, true);
|
||||
}
|
||||
|
||||
if (_mainCharacter.animFrame < 50 || _mainCharacter.animFrame > 87)
|
||||
return;
|
||||
|
||||
if (_mainCharacter.y1 == -1 || (_mainCharacter.x1 != -1 && _mainCharacter.animFrame == 87) || _mainCharacter.animFrame == 87) {
|
||||
_mainCharacter.animFrame = 87;
|
||||
} else {
|
||||
if (_goodConsciencePosition)
|
||||
_mainCharacter.facing = 3;
|
||||
else
|
||||
_mainCharacter.facing = 5;
|
||||
_mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
|
||||
}
|
||||
|
||||
updateCharacterAnim(0);
|
||||
refreshAnimObjectsIfNeed();
|
||||
}
|
||||
|
||||
void KyraEngine_MR::hideGoodConscience() {
|
||||
if (!_goodConscienceShown)
|
||||
return;
|
||||
|
||||
_goodConscienceShown = false;
|
||||
for (int frame = _goodConscienceFrameTable[_goodConscienceAnim+5]; frame >= 0; --frame) {
|
||||
if (frame == 17)
|
||||
snd_playSoundEffect(0x31, 0xC8);
|
||||
updateSceneAnim(0x0F, frame);
|
||||
delay(1*_tickLength, true);
|
||||
}
|
||||
|
||||
updateSceneAnim(0x0F, -1);
|
||||
update();
|
||||
removeSceneAnimObject(0x0F, 1);
|
||||
setNextIdleAnimTimer();
|
||||
}
|
||||
|
||||
void KyraEngine_MR::eelScript() {
|
||||
if (!_chatText.empty())
|
||||
return;
|
||||
_screen->hideMouse();
|
||||
|
||||
if (_inventoryState)
|
||||
hideInventory();
|
||||
removeHandItem();
|
||||
|
||||
objectChat((const char *)getTableEntry(_cCodeFile, 35), 0, 204, 35);
|
||||
objectChat((const char *)getTableEntry(_cCodeFile, 40), 0, 204, 40);
|
||||
|
||||
setGameFlag(0xD1);
|
||||
|
||||
snd_playSoundEffect(0x2A, 0xC8);
|
||||
|
||||
setGameFlag(0x171);
|
||||
|
||||
switch (_characterShapeFile-1) {
|
||||
case 0:
|
||||
runAnimationScript("EELS01.EMC", 0, 0, 1, 1);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
runAnimationScript("EELS02.EMC", 0, 0, 1, 1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
runAnimationScript("EELS03.EMC", 0, 0, 1, 1);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
runAnimationScript("EELS04.EMC", 0, 0, 1, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
resetGameFlag(0x171);
|
||||
runAnimationScript("EELS00.EMC", 0, 0, 1, 1);
|
||||
}
|
||||
|
||||
changeChapter(2, 29, 0, 4);
|
||||
_screen->showMouse();
|
||||
}
|
||||
|
||||
int KyraEngine_MR::initAnimationShapes(uint8 *filedata) {
|
||||
const int lastEntry = MIN(_animShapeLastEntry, 41);
|
||||
for (int i = 0; i < lastEntry; ++i)
|
||||
_gameShapes[9+i] = _screen->getPtrToShape(filedata, i);
|
||||
return lastEntry;
|
||||
}
|
||||
|
||||
void KyraEngine_MR::uninitAnimationShapes(int count, uint8 *filedata) {
|
||||
for (int i = 0; i < count; ++i)
|
||||
_gameShapes[9+i] = 0;
|
||||
delete[] filedata;
|
||||
setNextIdleAnimTimer();
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
130
engines/kyra/sequence/sequences_v2.cpp
Normal file
130
engines/kyra/sequence/sequences_v2.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/engine/kyra_v2.h"
|
||||
#include "kyra/resource/resource.h"
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
void KyraEngine_v2::runAnimationScript(const char *filename, int allowSkip, int resetChar, int newShapes, int shapeUnload) {
|
||||
memset(&_animationScriptData, 0, sizeof(_animationScriptData));
|
||||
memset(&_animationScriptState, 0, sizeof(_animationScriptState));
|
||||
|
||||
if (!_emc->load(filename, &_animationScriptData, &_opcodesAnimation))
|
||||
error("Couldn't load temporary script '%s'", filename);
|
||||
|
||||
_emc->init(&_animationScriptState, &_animationScriptData);
|
||||
_emc->start(&_animationScriptState, 0);
|
||||
|
||||
_animResetFrame = -1;
|
||||
|
||||
if (_animShapeFiledata && newShapes) {
|
||||
uninitAnimationShapes(_animShapeCount, _animShapeFiledata);
|
||||
_animShapeFiledata = nullptr;
|
||||
_animShapeCount = 0;
|
||||
}
|
||||
|
||||
while (_emc->isValid(&_animationScriptState))
|
||||
_emc->run(&_animationScriptState);
|
||||
|
||||
uint8 *fileData = nullptr;
|
||||
|
||||
if (newShapes)
|
||||
_animShapeFiledata = _res->fileData(_animShapeFilename, nullptr);
|
||||
|
||||
fileData = _animShapeFiledata;
|
||||
|
||||
if (!fileData) {
|
||||
_emc->unload(&_animationScriptData);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newShapes)
|
||||
_animShapeCount = initAnimationShapes(fileData);
|
||||
|
||||
processAnimationScript(allowSkip, resetChar);
|
||||
|
||||
if (shapeUnload) {
|
||||
uninitAnimationShapes(_animShapeCount, fileData);
|
||||
_animShapeCount = 0;
|
||||
_animShapeFiledata = nullptr;
|
||||
}
|
||||
|
||||
_emc->unload(&_animationScriptData);
|
||||
}
|
||||
|
||||
void KyraEngine_v2::processAnimationScript(int allowSkip, int resetChar) {
|
||||
setCharacterAnimDim(_animShapeWidth, _animShapeHeight);
|
||||
|
||||
_emc->init(&_animationScriptState, &_animationScriptData);
|
||||
_emc->start(&_animationScriptState, 1);
|
||||
|
||||
resetSkipFlag();
|
||||
|
||||
while (_emc->isValid(&_animationScriptState)) {
|
||||
_animNeedUpdate = false;
|
||||
while (_emc->isValid(&_animationScriptState) && !_animNeedUpdate)
|
||||
_emc->run(&_animationScriptState);
|
||||
|
||||
if (_animNewFrame < 0)
|
||||
continue;
|
||||
|
||||
_mainCharacter.animFrame = _animNewFrame + _desc.animScriptFrameAdd;
|
||||
updateCharacterAnim(0);
|
||||
if (!_chatText.empty())
|
||||
updateWithText();
|
||||
else
|
||||
update();
|
||||
|
||||
uint32 delayEnd = _system->getMillis() + _animDelayTime * _tickLength;
|
||||
|
||||
while ((!skipFlag() || !allowSkip) && _system->getMillis() < delayEnd)
|
||||
delay(10, true);
|
||||
|
||||
if (skipFlag()) {
|
||||
if (!_kbEventSkip || _eventList.front().event.type != Common::EVENT_KEYDOWN)
|
||||
resetSkipFlag();
|
||||
if (allowSkip)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (resetChar) {
|
||||
if (_animResetFrame >= 0) {
|
||||
_mainCharacter.animFrame = _animResetFrame + _desc.animScriptFrameAdd;
|
||||
updateCharacterAnim(0);
|
||||
if (!_chatText.empty())
|
||||
updateWithText();
|
||||
else
|
||||
update();
|
||||
}
|
||||
|
||||
_mainCharacter.animFrame = _desc.characterFrameTable[_mainCharacter.facing];
|
||||
updateCharacterAnim(0);
|
||||
}
|
||||
|
||||
_animResetFrame = -1;
|
||||
resetCharacterAnimDim();
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
Reference in New Issue
Block a user