aboutsummaryrefslogtreecommitdiff
path: root/engines/prince/prince.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/prince/prince.cpp')
-rw-r--r--engines/prince/prince.cpp219
1 files changed, 166 insertions, 53 deletions
diff --git a/engines/prince/prince.cpp b/engines/prince/prince.cpp
index 29c434e9c9..55f12a6560 100644
--- a/engines/prince/prince.cpp
+++ b/engines/prince/prince.cpp
@@ -61,6 +61,7 @@
#include "prince/animation.h"
#include "prince/option_text.h"
#include "prince/curve_values.h"
+#include "prince/detection.h"
namespace Prince {
@@ -95,7 +96,8 @@ PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc)
_tracePointFirstPointFlag(false), _coordsBuf2(nullptr), _coords2(nullptr), _coordsBuf3(nullptr), _coords3(nullptr),
_shanLen(0), _directionTable(nullptr), _currentMidi(0), _lightX(0), _lightY(0), _curveData(nullptr), _curvPos(0),
_creditsData(nullptr), _creditsDataSize(0), _currentTime(0), _zoomBitmap(nullptr), _shadowBitmap(nullptr), _transTable(nullptr),
- _flcFrameSurface(nullptr), _shadScaleValue(0), _shadLineLen(0), _scaleValue(0), _dialogImage(nullptr) {
+ _flcFrameSurface(nullptr), _shadScaleValue(0), _shadLineLen(0), _scaleValue(0), _dialogImage(nullptr), _mobTranslationData(nullptr),
+ _mobTranslationSize(0) {
// Debug/console setup
DebugMan.addDebugChannel(DebugChannel::kScript, "script", "Prince Script debug channel");
@@ -204,6 +206,8 @@ PrinceEngine::~PrinceEngine() {
_dialogImage->free();
delete _dialogImage;
}
+
+ free(_mobTranslationData);
}
GUI::Debugger *PrinceEngine::getDebugger() {
@@ -213,11 +217,11 @@ GUI::Debugger *PrinceEngine::getDebugger() {
void PrinceEngine::init() {
const Common::FSNode gameDataDir(ConfMan.get("path"));
-
+
debugEngine("Adding all path: %s", gameDataDir.getPath().c_str());
PtcArchive *all = new PtcArchive();
- if (!all->open("all/databank.ptc"))
+ if (!all->open("all/databank.ptc"))
error("Can't open all/databank.ptc");
PtcArchive *voices = new PtcArchive();
@@ -228,11 +232,20 @@ void PrinceEngine::init() {
if (!sound->open("sound/databank.ptc"))
error("Can't open sound/databank.ptc");
+ PtcArchive *translation = new PtcArchive();
+ if (getLanguage() != Common::PL_POL && getLanguage() != Common::DE_DEU) {
+ if (!translation->openTranslation("all/prince_translation.dat"))
+ error("Can't open prince_translation.dat");
+ }
+
SearchMan.addSubDirectoryMatching(gameDataDir, "all");
SearchMan.add("all", all);
SearchMan.add("voices", voices);
SearchMan.add("sound", sound);
+ if (getLanguage() != Common::PL_POL && getLanguage() != Common::DE_DEU) {
+ SearchMan.add("translation", translation);
+ }
_graph = new GraphicsMan(this);
@@ -260,15 +273,24 @@ void PrinceEngine::init() {
_debugger = new Debugger(this, _flags);
_variaTxt = new VariaTxt();
- Resource::loadResource(_variaTxt, "variatxt.dat", true);
-
+ if (getLanguage() == Common::PL_POL || getLanguage() == Common::DE_DEU) {
+ Resource::loadResource(_variaTxt, "variatxt.dat", true);
+ } else {
+ Resource::loadResource(_variaTxt, "variatxt_translate.dat", true);
+ }
+
_cursor1 = new Cursor();
Resource::loadResource(_cursor1, "mouse1.cur", true);
_cursor3 = new Cursor();
Resource::loadResource(_cursor3, "mouse2.cur", true);
- Common::SeekableReadStream *talkTxtStream = SearchMan.createReadStreamForMember("talktxt.dat");
+ Common::SeekableReadStream *talkTxtStream;
+ if (getLanguage() == Common::PL_POL || getLanguage() == Common::DE_DEU) {
+ talkTxtStream = SearchMan.createReadStreamForMember("talktxt.dat");
+ } else {
+ talkTxtStream = SearchMan.createReadStreamForMember("talktxt_translate.dat");
+ }
if (!talkTxtStream) {
error("Can't load talkTxtStream");
return;
@@ -279,7 +301,12 @@ void PrinceEngine::init() {
delete talkTxtStream;
- Common::SeekableReadStream *invTxtStream = SearchMan.createReadStreamForMember("invtxt.dat");
+ Common::SeekableReadStream *invTxtStream;
+ if (getLanguage() == Common::PL_POL || getLanguage() == Common::DE_DEU) {
+ invTxtStream = SearchMan.createReadStreamForMember("invtxt.dat");
+ } else {
+ invTxtStream = SearchMan.createReadStreamForMember("invtxt_translate.dat");
+ }
if (!invTxtStream) {
error("Can't load invTxtStream");
return;
@@ -354,7 +381,12 @@ void PrinceEngine::init() {
_shadowLine = (byte *)malloc(kShadowLineArraySize);
- Common::SeekableReadStream *creditsDataStream = SearchMan.createReadStreamForMember("credits.dat");
+ Common::SeekableReadStream *creditsDataStream;
+ if (getLanguage() == Common::PL_POL || getLanguage() == Common::DE_DEU) {
+ creditsDataStream = SearchMan.createReadStreamForMember("credits.dat");
+ } else {
+ creditsDataStream = SearchMan.createReadStreamForMember("credits_translate.dat");
+ }
if (!creditsDataStream) {
error("Can't load creditsDataStream");
return;
@@ -363,11 +395,14 @@ void PrinceEngine::init() {
_creditsData = (byte *)malloc(_creditsDataSize);
creditsDataStream->read(_creditsData, _creditsDataSize);
delete creditsDataStream;
+
+ if (getLanguage() != Common::PL_POL && getLanguage() != Common::DE_DEU) {
+ loadMobTranslationTexts();
+ }
}
void PrinceEngine::showLogo() {
MhwanhDecoder logo;
- _system->delayMillis(1000 / kFPS * 20);
if (Resource::loadResource(&logo, "logo.raw", true)) {
loadSample(0, "LOGO.WAV");
playSample(0, 0);
@@ -375,21 +410,58 @@ void PrinceEngine::showLogo() {
_graph->change();
_graph->update(_graph->_frontScreen);
setPalette(logo.getPalette());
- _system->delayMillis(1000 / kFPS * 70);
+
+ uint32 logoStart = _system->getMillis();
+ while (_system->getMillis() < logoStart + 5000) {
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
+ stopSample(0);
+ return;
+ }
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ stopSample(0);
+ return;
+ default:
+ break;
+ }
+ }
+
+ if (shouldQuit()) {
+ return;
+ }
+ }
}
}
Common::Error PrinceEngine::run() {
-
+ syncSoundSettings();
+ int startGameSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
init();
-
- showLogo();
-
+ if (startGameSlot == -1) {
+ showLogo();
+ } else {
+ loadLocation(59); // load intro location - easiest way to set everything up
+ loadGame(startGameSlot);
+ }
mainLoop();
-
return Common::kNoError;
}
+void PrinceEngine::pauseEngineIntern(bool pause) {
+ Engine::pauseEngineIntern(pause);
+ if (pause) {
+ _midiPlayer->pause();
+ }
+ else {
+ _midiPlayer->resume();
+ }
+}
+
bool AnimListItem::loadFromStream(Common::SeekableReadStream &stream) {
int32 pos = stream.pos();
@@ -469,13 +541,17 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
loadMobPriority("mobpri");
_mobList.clear();
- if (getLanguage() == Common::DE_DEU) {
+ if (getGameType() == kPrinceDataDE) {
const Common::String mobLstName = Common::String::format("mob%02d.lst", _locationNr);
debug("name: %s", mobLstName.c_str());
Resource::loadResource(_mobList, mobLstName.c_str(), false);
- } else {
+ } else if (getGameType() == kPrinceDataPL) {
Resource::loadResource(_mobList, "mob.lst", false);
}
+ if (getLanguage() != Common::PL_POL && getLanguage() != Common::DE_DEU) {
+ // update Mob texts for translated version
+ setMobTranslationTexts();
+ }
_animList.clear();
Resource::loadResource(_animList, "anim.lst", false);
@@ -678,7 +754,11 @@ void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) {
return;
}
_audioStream[sampleId]->rewind();
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ if (sampleId < 28) {
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ } else {
+ _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ }
}
}
@@ -705,7 +785,7 @@ void PrinceEngine::freeAllSamples() {
}
bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) {
- // FIXME: This is just a workaround streamName is a path
+ // 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, '\\');
@@ -730,8 +810,8 @@ bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamNam
bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) {
debugEngine("Loading wav %s slot %d", streamName.c_str(), slot);
- if (slot > kMaxTexts) {
- error("Text slot bigger than MAXTEXTS %d", kMaxTexts);
+ if (slot >= kMaxTexts) {
+ error("Text slot bigger than MAXTEXTS %d", kMaxTexts - 1);
return false;
}
@@ -756,7 +836,7 @@ bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::Strin
}
id = sampleStream->readUint32LE();
- debugEngine("SetVoice slot %d time %04x", slot, id);
+ debugEngine("SetVoice slot %d time %04x", slot, id);
id <<= 3;
id /= 22050;
id += 2;
@@ -768,7 +848,7 @@ bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::Strin
_secondHero->_talkTime = id;
}
- debugEngine("SetVoice slot %d time %04x", slot, id);
+ debugEngine("SetVoice slot %d time %04x", slot, id);
sampleStream->seek(SEEK_SET);
_audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream, DisposeAfterUse::NO);
delete sampleStream;
@@ -947,6 +1027,45 @@ bool PrinceEngine::loadMobPriority(const char *resourceName) {
return true;
}
+void PrinceEngine::loadMobTranslationTexts() {
+ Common::SeekableReadStream *mobTranslationStream = SearchMan.createReadStreamForMember("mob_translate.dat");
+ if (!mobTranslationStream) {
+ error("Can't load mob_translate.dat");
+ }
+ _mobTranslationSize = mobTranslationStream->size();
+ _mobTranslationData = (byte *)malloc(_mobTranslationSize);
+ mobTranslationStream->read(_mobTranslationData, _mobTranslationSize);
+ delete mobTranslationStream;
+}
+
+void PrinceEngine::setMobTranslationTexts() {
+ int locationOffset = READ_UINT16(_mobTranslationData + (_locationNr - 1) * 2);
+ if (locationOffset) {
+ byte *locationText = _mobTranslationData + locationOffset;
+ for (uint i = 0; i < _mobList.size(); i++) {
+ byte c;
+ locationText++;
+ _mobList[i]._name.clear();
+ while ((c = *locationText)) {
+ _mobList[i]._name += c;
+ locationText++;
+ }
+ locationText++;
+ _mobList[i]._examText.clear();
+ c = *locationText;
+ locationText++;
+ if (c) {
+ _mobList[i]._examText += c;
+ do {
+ c = *locationText;
+ _mobList[i]._examText += c;
+ locationText++;
+ } while (c != 255);
+ }
+ }
+ }
+}
+
void PrinceEngine::keyHandler(Common::Event event) {
uint16 nChar = event.kbd.keycode;
switch (nChar) {
@@ -1506,7 +1625,7 @@ void PrinceEngine::setBackAnim(Anim &backAnim) {
}
void PrinceEngine::showBackAnims() {
- for (uint i = 0; i < kMaxBackAnims; i++) {
+ for (int i = 0; i < kMaxBackAnims; i++) {
BAS &seq = _backAnimList[i]._seq;
int activeSubAnim = seq._currRelative;
if (!_backAnimList[i].backAnims.empty()) {
@@ -1893,7 +2012,7 @@ void PrinceEngine::blackPalette() {
free(blackPalette1);
return;
}
- pause();
+ pausePrinceEngine();
}
free(paletteBackup);
free(blackPalette1);
@@ -1901,41 +2020,34 @@ void PrinceEngine::blackPalette() {
void PrinceEngine::setPalette(const byte *palette) {
if (palette != nullptr) {
- byte *blackPalette = (byte *)malloc(256 * 3);
+ byte *blackPalette_ = (byte *)malloc(256 * 3);
int fadeStep = 0;
for (int i = 0; i <= kFadeStep; i++) {
for (int j = 0; j < 256; j++) {
- blackPalette[3 * j] = palette[3 * j] * fadeStep / 4;
- blackPalette[3 * j + 1] = palette[3 * j + 1] * fadeStep / 4;
- blackPalette[3 * j + 2] = palette[3 * j + 2] * fadeStep / 4;
+ blackPalette_[3 * j] = palette[3 * j] * fadeStep / 4;
+ blackPalette_[3 * j + 1] = palette[3 * j + 1] * fadeStep / 4;
+ blackPalette_[3 * j + 2] = palette[3 * j + 2] * fadeStep / 4;
}
fadeStep++;
- _graph->setPalette(blackPalette);
+ _graph->setPalette(blackPalette_);
_system->updateScreen();
Common::Event event;
Common::EventManager *eventMan = _system->getEventManager();
eventMan->pollEvent(event);
if (shouldQuit()) {
_graph->setPalette(palette);
- free(blackPalette);
+ free(blackPalette_);
return;
}
- pause();
+ pausePrinceEngine();
}
_graph->setPalette(palette);
- free(blackPalette);
+ free(blackPalette_);
}
}
-void PrinceEngine::pause() {
- int delay = 1000 / kFPS - int32(_system->getMillis() - _currentTime);
- delay = delay < 0 ? 0 : delay;
- _system->delayMillis(delay);
- _currentTime = _system->getMillis();
-}
-
-void PrinceEngine::pause2() {
- int delay = 1000 / (kFPS * 2) - int32(_system->getMillis() - _currentTime);
+void PrinceEngine::pausePrinceEngine(int fps) {
+ int delay = 1000 / fps - int32(_system->getMillis() - _currentTime);
delay = delay < 0 ? 0 : delay;
_system->delayMillis(delay);
_currentTime = _system->getMillis();
@@ -2048,7 +2160,7 @@ void PrinceEngine::addInvObj() {
if (shouldQuit()) {
return;
}
- pause();
+ pausePrinceEngine();
}
while (_mst_shadow2 > 256) {
rememberScreenInv();
@@ -2062,7 +2174,7 @@ void PrinceEngine::addInvObj() {
if (shouldQuit()) {
return;
}
- pause();
+ pausePrinceEngine();
}
} else {
//CURSEBLINK:
@@ -2080,7 +2192,7 @@ void PrinceEngine::addInvObj() {
if (shouldQuit()) {
return;
}
- pause();
+ pausePrinceEngine();
}
while (_mst_shadow2 > 256) {
rememberScreenInv();
@@ -2094,7 +2206,7 @@ void PrinceEngine::addInvObj() {
if (shouldQuit()) {
return;
}
- pause();
+ pausePrinceEngine();
}
}
}
@@ -2110,7 +2222,7 @@ void PrinceEngine::addInvObj() {
if (shouldQuit()) {
return;
}
- pause();
+ pausePrinceEngine();
}
}
@@ -2305,6 +2417,7 @@ void PrinceEngine::moveRunHero(int heroId, int x, int y, int dir, bool runHeroFl
}
void PrinceEngine::leftMouseButton() {
+ _flags->setFlagValue(Flags::ESCAPED2, 1); // skip intro animation
_flags->setFlagValue(Flags::LMOUSE, 1);
if (_flags->getFlagValue(Flags::POWERENABLED)) {
_flags->setFlagValue(Flags::MBFLAG, 1);
@@ -2738,7 +2851,7 @@ void PrinceEngine::displayInventory() {
getDebugger()->onFrame();
_graph->update(_graph->_screenForInventory);
- pause();
+ pausePrinceEngine();
}
if (_currentPointerNumber == 2) {
@@ -2863,7 +2976,7 @@ void PrinceEngine::dialogRun() {
getDebugger()->onFrame();
_graph->update(_graph->_frontScreen);
- pause();
+ pausePrinceEngine();
}
_dialogImage->free();
delete _dialogImage;
@@ -3122,7 +3235,7 @@ void PrinceEngine::scrollCredits() {
}
_graph->change();
_graph->update(_graph->_frontScreen);
- pause2();
+ pausePrinceEngine(kFPS * 2);
}
char letter2;
byte *scan2 = scrollAdress;
@@ -4106,7 +4219,7 @@ int PrinceEngine::checkRightUpDir() {
}
bool PrinceEngine::tracePath(int x1, int y1, int x2, int y2) {
- for (int i = 0; i < kPathBitmapLen; i++) {
+ for (uint i = 0; i < kPathBitmapLen; i++) {
_roomPathBitmapTemp[i] = 0;
}
if (x1 != x2 || y1 != y2) {
@@ -4321,7 +4434,7 @@ int PrinceEngine::scanDirectionsFindNext(byte *tempCoordsBuf, int xDiff, int yDi
tempCoordsBuf += 4;
if (tempCoordsBuf == _coords) {
- direction = tempX;
+ direction = tempX;
break;
}
@@ -4726,7 +4839,7 @@ void PrinceEngine::mainLoop() {
openInventoryCheck();
- pause();
+ pausePrinceEngine();
}
}