mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
624 lines
18 KiB
C++
624 lines
18 KiB
C++
/* 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
|