From 69a58457744c662930f5f19b90d95d7647d580b2 Mon Sep 17 00:00:00 2001 From: Kamil Zbróg Date: Tue, 3 Dec 2013 14:46:24 +0000 Subject: PRINCE: loadSample with sample looping added, escaping from intro works --- engines/prince/archive.cpp | 1 + engines/prince/font.h | 8 ++--- engines/prince/hero.cpp | 34 ++++++++++++++++++ engines/prince/hero.h | 88 ++++++++++++++++++++++++++++++++++++++++++++++ engines/prince/module.mk | 1 + engines/prince/prince.cpp | 68 ++++++++++++++++++++++++++--------- engines/prince/prince.h | 13 +++++-- engines/prince/script.cpp | 19 +++++++--- 8 files changed, 205 insertions(+), 27 deletions(-) create mode 100644 engines/prince/hero.cpp create mode 100644 engines/prince/hero.h diff --git a/engines/prince/archive.cpp b/engines/prince/archive.cpp index 0b1367f966..d1b680c204 100644 --- a/engines/prince/archive.cpp +++ b/engines/prince/archive.cpp @@ -86,6 +86,7 @@ void PtcArchive::close() { } bool PtcArchive::hasFile(const Common::String &name) const { + // TODO: check if path matching should be added return _items.contains(name); } diff --git a/engines/prince/font.h b/engines/prince/font.h index c41b176c72..bf9c09d0e9 100644 --- a/engines/prince/font.h +++ b/engines/prince/font.h @@ -41,13 +41,13 @@ public: bool loadFromStream(Common::SeekableReadStream &stream); - virtual int getFontHeight() const override; + virtual int getFontHeight() const override; - virtual int getMaxCharWidth() const override; + virtual int getMaxCharWidth() const override; - virtual int getCharWidth(uint32 chr) const override; + virtual int getCharWidth(uint32 chr) const override; - virtual void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override; + virtual void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override; virtual int getKerningOffset(uint32 left, uint32 right) const override { return -2; } diff --git a/engines/prince/hero.cpp b/engines/prince/hero.cpp new file mode 100644 index 0000000000..277e521bee --- /dev/null +++ b/engines/prince/hero.cpp @@ -0,0 +1,34 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "prince/hero.h" + +namespace Prince { + +Hero::Hero() : _number(0), _visible(false), _state(STAY), _middleX(0), _middleY(0) + , _boreNum(0), _currHeight(0), _moveDelay(0), _shadMinus(1) +{ +} + +} + +/* vim: set tabstop=4 noexpandtab: */ diff --git a/engines/prince/hero.h b/engines/prince/hero.h new file mode 100644 index 0000000000..e11a0f7395 --- /dev/null +++ b/engines/prince/hero.h @@ -0,0 +1,88 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef PRINCE_HERO_H +#define PRINCE_HERO_H + +#include "common/scummsys.h" + +namespace Prince { + +class Hero { +public: + enum State { + STAY = 0, + TURN = 1, + MOVE = 2, + BORE = 3, + SPEC = 4, + TALK = 5, + MVAN = 6, + TRAN = 7, + RUN = 8, + DMOVE = 9 + }; + + Hero(); + +private: + uint16 _number; + uint16 _visible; + State _state; + uint16 _middleX; + uint16 _middleY; + + // Coords array of coordinates + // DirTab array of directions + // CurrCoords current coordinations + // CurrDirTab current direction + // LastDir previous move direction + // DestDir + // LeftRight previous left/right direction + // UpDown previous up/down direction + // Phase animation phase + // Step x/y step size depends on direction + // MaxBoredom stand still timeout + // Boredom current boredom time in frames + uint16 _boreNum; // Bore anim frame + // TalkTime time of talk anim + // SpecAnim additional anim + + uint16 _currHeight; // height of current anim phase + + // Inventory array of items + // Inventory2 array of items + // Font subtitiles font + // Color subtitiles color + // AnimSet number of animation set + // MoveAnims MoveSet + // TurnAnim ?? + + uint32 _moveDelay; + uint32 _shadMinus; //?? +}; + +} + +#endif + +/* vim: set tabstop=4 noexpandtab: */ diff --git a/engines/prince/module.mk b/engines/prince/module.mk index 48edcec9dd..2e5f0592b1 100644 --- a/engines/prince/module.mk +++ b/engines/prince/module.mk @@ -15,6 +15,7 @@ MODULE_OBJS = \ prince.o \ archive.o \ decompress.o \ + hero.o \ cursor.o # This module can be built as a plugin diff --git a/engines/prince/prince.cpp b/engines/prince/prince.cpp index 9f4ae19af3..f82f9e0e0c 100644 --- a/engines/prince/prince.cpp +++ b/engines/prince/prince.cpp @@ -31,6 +31,7 @@ #include "common/fs.h" #include "common/keyboard.h" #include "common/substream.h" +#include "common/str.h" #include "graphics/cursorman.h" #include "graphics/surface.h" @@ -56,6 +57,7 @@ #include "prince/mhwanh.h" #include "prince/cursor.h" #include "prince/archive.h" +#include "prince/hero.h" namespace Prince { @@ -74,7 +76,7 @@ PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc) Engine(syst), _gameDescription(gameDesc), _graph(NULL), _script(NULL), _locationNr(0), _debugger(NULL), _midiPlayer(NULL), _cameraX(0), _newCameraX(0), _frameNr(0), _cursor1(NULL), _cursor2(NULL), _font(NULL), - _walizkaBmp(NULL), _roomBmp(NULL), _voiceStream(NULL), _cursorNr(0) { + _walizkaBmp(NULL), _roomBmp(NULL), _cursorNr(0) { // Debug/console setup DebugMan.addDebugChannel(DebugChannel::kScript, "script", "Prince Script debug channel"); @@ -82,6 +84,8 @@ PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc) DebugMan.enableDebugChannel("script"); + memset(_voiceStream, 0, sizeof(_voiceStream)); + gDebugLevel = 10; } @@ -196,17 +200,19 @@ void PrinceEngine::init() { if (!voices->open("data/voices/databank.ptc")) error("Can't open data/voices/databank.ptc"); + PtcArchive *sound = new PtcArchive(); + if (!sound->open("sound/databank.ptc")) + error("Can't open sound/databank.ptc"); + SearchMan.add("all", all); SearchMan.add("data/voices", voices); + SearchMan.add("sound", sound); _graph = new GraphicsMan(this); _rnd = new Common::RandomSource("prince"); _debugger = new Debugger(this); - SearchMan.addSubDirectoryMatching(gameDataDir, "all", 0, 2); - SearchMan.addSubDirectoryMatching(gameDataDir, "data/voices", 0, 2); - _midiPlayer = new MusicPlayer(this); _font = new Font(); @@ -263,6 +269,13 @@ Common::Error PrinceEngine::run() { } bool PrinceEngine::loadLocation(uint16 locationNr) { + _flicPlayer.close(); + + memset(_textSlots, 0, sizeof(_textSlots)); + for(uint32 sampleId = 0; sampleId < MAX_SAMPLES; ++sampleId) { + stopSample(sampleId); + } + debugEngine("PrinceEngine::loadLocation %d", locationNr); const Common::FSNode gameDataDir(ConfMan.get("path")); SearchMan.remove(Common::String::format("%02d", _locationNr)); @@ -357,19 +370,42 @@ bool PrinceEngine::playNextFrame() { } void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) { - if (_voiceStream) { + if (_voiceStream[sampleId]) { - Audio::RewindableAudioStream *audioStream = Audio::makeWAVStream(_voiceStream, DisposeAfterUse::YES); - _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, audioStream, sampleId); + if (_mixer->isSoundIDActive(sampleId)) { + return; + } + + Audio::AudioStream *audioStream = Audio::makeWAVStream(_voiceStream[sampleId], DisposeAfterUse::YES); + if (loopType) { + audioStream = new Audio::LoopingAudioStream((Audio::RewindableAudioStream*)audioStream, 0, DisposeAfterUse::NO); + } + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], audioStream, sampleId); } } void PrinceEngine::stopSample(uint16 sampleId) { _mixer->stopID(sampleId); - _voiceStream = NULL; + _voiceStream[sampleId] = NULL; +} + +bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) { + // FIXME: This is just a workaround streamName is a path + // SOUND\\SCIERKA1.WAV for now only last path component is used + Common::String normalizedPath = lastPathComponent(streamName, '\\'); + + debugEngine("loadSample slot %d, name %s", sampleSlot, normalizedPath.c_str()); + + _mixer->stopID(sampleSlot); + _voiceStream[sampleSlot] = NULL; + _voiceStream[sampleSlot] = SearchMan.createReadStreamForMember(normalizedPath); + if (_voiceStream[sampleSlot] == NULL) { + error("Can't load sample %s to slot %d", normalizedPath.c_str(), sampleSlot); + } + return _voiceStream[sampleSlot] == NULL; } -bool PrinceEngine::loadVoice(uint32 slot, const Common::String &streamName) { +bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) { debugEngine("Loading wav %s slot %d", streamName.c_str(), slot); if (slot > MAXTEXTS) { @@ -377,26 +413,26 @@ bool PrinceEngine::loadVoice(uint32 slot, const Common::String &streamName) { return false; } - _voiceStream = SearchMan.createReadStreamForMember(streamName); - if (!_voiceStream) { + _voiceStream[sampleSlot] = SearchMan.createReadStreamForMember(streamName); + if (!_voiceStream[sampleSlot]) { error("Can't open %s", streamName.c_str()); return false; } - uint32 id = _voiceStream->readUint32LE(); + uint32 id = _voiceStream[sampleSlot]->readUint32LE(); if (id != 0x46464952) { error("It's not RIFF file %s", streamName.c_str()); return false; } - _voiceStream->skip(0x20); - id = _voiceStream->readUint32LE(); + _voiceStream[sampleSlot]->skip(0x20); + id = _voiceStream[sampleSlot]->readUint32LE(); if (id != 0x61746164) { error("No data section in %s id %04x", streamName.c_str(), id); return false; } - id = _voiceStream->readUint32LE(); + id = _voiceStream[sampleSlot]->readUint32LE(); debugEngine("SetVoice slot %d time %04x", slot, id); id <<= 3; id /= 22050; @@ -405,7 +441,7 @@ bool PrinceEngine::loadVoice(uint32 slot, const Common::String &streamName) { _textSlots[slot]._time = id; debugEngine("SetVoice slot %d time %04x", slot, id); - _voiceStream->seek(0); + _voiceStream[sampleSlot]->seek(0); return true; } diff --git a/engines/prince/prince.h b/engines/prince/prince.h index 374048f285..d2c75e76cb 100644 --- a/engines/prince/prince.h +++ b/engines/prince/prince.h @@ -59,6 +59,7 @@ class VariaTxt; class Cursor; class MhwanhDecoder; class Font; +class Hero; struct Text { const char *_str; @@ -103,7 +104,8 @@ public: bool loadLocation(uint16 locationNr); bool loadAnim(uint16 animNr, bool loop); - bool loadVoice(uint32 slot, const Common::String &name); + bool loadVoice(uint32 textSlot, uint32 sampleSlot, const Common::String &name); + bool loadSample(uint32 sampleSlot, const Common::String &name); void playSample(uint16 sampleId, uint16 loopType); void stopSample(uint16 sampleId); @@ -146,8 +148,11 @@ private: Font *_font; MusicPlayer *_midiPlayer; - Audio::SoundHandle _soundHandle; - Common::SeekableReadStream *_voiceStream; + + static const uint32 MAX_SAMPLES = 60; + Common::SeekableReadStream *_voiceStream[MAX_SAMPLES]; + Audio::SoundHandle _soundHandle[MAX_SAMPLES]; + Common::Array _mobList; Common::Array _objList; @@ -155,6 +160,8 @@ private: uint16 _newCameraX; uint16 _sceneWidth; + Hero* _mainHero; + bool _flicLooped; void mainLoop(); diff --git a/engines/prince/script.cpp b/engines/prince/script.cpp index 07821f27a8..9daf3048ab 100644 --- a/engines/prince/script.cpp +++ b/engines/prince/script.cpp @@ -41,6 +41,7 @@ static const uint16 NUM_OPCODES = 144; Script::Script(PrinceEngine *vm) : _code(NULL), _stacktop(0), _vm(vm), _opcodeNF(false), _waitFlag(0), _result(true) { + memset(_flags, 0, sizeof(_flags)); } Script::~Script() { @@ -146,7 +147,7 @@ uint16 Script::readScript16bits() { uint16 Script::readScriptValue() { uint16 value = readScript16bits(); if (value & FLAG_MASK) { - value = _flags[value - FLAG_MASK]; + return getFlagValue((Flags::Id)value); } return value; } @@ -183,6 +184,7 @@ void Script::O_SETSAMPLE() { int32 sampleNameOffset = readScript32bits(); const char * sampleName = (const char *)&_code[_currentInstruction + sampleNameOffset - 4]; debugScript("O_SETSAMPLE %d %s", sampleId, sampleName); + _vm->loadSample(sampleId, sampleName); } void Script::O_FREESAMPLE() { @@ -355,6 +357,7 @@ void Script::O_BACKANIMUPDATEON() { void Script::O_CHANGECURSOR() { uint16 cursorId = readScriptValue(); debugScript("O_CHANGECURSOR %x", cursorId); + _vm->changeCursor(cursorId); } void Script::O_CHANGEANIMTYPE() { @@ -765,7 +768,7 @@ void Script::O_GETANIMDATA() { void Script::O_SETBGCODE() { int32 offset = readScript32bits(); - _bgOpcodePC = _currentInstruction + offset; + _bgOpcodePC = _currentInstruction + offset - 4; debugScript("O_SETBGCODE next %08x, offset %08x", _bgOpcodePC, offset); } @@ -926,11 +929,18 @@ void Script::O_STOPSAMPLE() { void Script::O_BACKANIMRANGE() { uint16 slotId = readScriptValue(); - uint16 animId = readScriptValue(); + uint16 animId = readScript16bits(); uint16 low = readScriptValue(); uint16 high = readScriptValue(); + if (animId != 0xFFFF) { + if (animId & FLAG_MASK) { + animId = getFlagValue((Flags::Id)animId); + } + } + debugScript("O_BACKANIMRANGE slotId %d, animId %d, low %d, high %d", slotId, animId, low, high); + _result = 1; } void Script::O_CLEARPATH() { @@ -982,7 +992,7 @@ void Script::O_POPSTRING() { void Script::O_SETFGCODE() { int32 offset = readScript32bits(); - _fgOpcodePC = _currentInstruction + offset; + _fgOpcodePC = _currentInstruction + offset - 4; debugScript("O_SETFGCODE next %08x, offset %08x", _fgOpcodePC, offset); } @@ -1125,6 +1135,7 @@ void Script::SetVoice(uint32 sampleSlot) { uint16 slot = readScriptValue(); _vm->loadVoice( slot, + sampleSlot, Common::String::format( "%03d-%02d.WAV", _currentString, -- cgit v1.2.3