From 3465571b121fdcaba1b97f0a52b1aa16a25390a5 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 12 Aug 2007 19:11:37 +0000 Subject: Added preliminary support for loading locations in BRA: - changed parseLocation to invoke subclasses for version-specific keywords. - implemented loading of background resources (backgrounds should be visible) svn-id: r28568 --- engines/parallaction/commands.cpp | 7 +- engines/parallaction/disk_br.cpp | 56 ++++++++- engines/parallaction/location.cpp | 188 +++++++++++++------------------ engines/parallaction/parallaction.h | 3 + engines/parallaction/parallaction_br.cpp | 78 +++++++++++++ engines/parallaction/parallaction_ns.cpp | 43 +++++++ engines/parallaction/parser.cpp | 2 +- 7 files changed, 263 insertions(+), 114 deletions(-) diff --git a/engines/parallaction/commands.cpp b/engines/parallaction/commands.cpp index dc392fde2c..915d76d7cc 100644 --- a/engines/parallaction/commands.cpp +++ b/engines/parallaction/commands.cpp @@ -183,7 +183,12 @@ void Parallaction::parseCommands(Script &script, CommandList& list) { } - list.push_front(cmd); // NOTE: command lists are written backwards in scripts + // FIXME: implement a proper parseCommands for BRA + if (getGameType() == GType_BRA) + delete cmd; + else + list.push_front(cmd); // NOTE: command lists are written backwards in scripts + fillBuffers(script, true); } diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index 65332a2a4a..b79af9c655 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -25,6 +25,7 @@ #include "common/stdafx.h" #include "parallaction/parallaction.h" +#include "parallaction/util.h" namespace Parallaction { @@ -87,17 +88,17 @@ Cnv* DosDisk_br::loadTalk(const char *name) { Script* DosDisk_br::loadLocation(const char *name) { debugC(5, kDebugDisk, "DosDisk_br::loadLocation"); - Common::File stream; + Common::File *stream = new Common::File; char path[PATH_LEN]; sprintf(path, "%s/%s/%s.slf", _partPath, _languageDir, name); - if (!stream.open(path)) { + if (!stream->open(path)) { sprintf(path, "%s/%s/%s.loc", _partPath, _languageDir, name); - if (!stream.open(path)) + if (!stream->open(path)) errorFileNotFound(path); } - return new Script(&stream, false); + return new Script(stream, true); } Script* DosDisk_br::loadScript(const char* name) { @@ -205,6 +206,53 @@ void DosDisk_br::loadSlide(BackgroundInfo& info, const char *name) { void DosDisk_br::loadScenery(BackgroundInfo& info, const char *name, const char *mask, const char* path) { debugC(5, kDebugDisk, "DosDisk_br::loadScenery"); + + char filename[PATH_LEN]; + Common::File stream; + + if (name) { + sprintf(filename, "%s/bkg/%s.bkg", _partPath, name); + if (!stream.open(filename)) + errorFileNotFound(filename); + + stream.skip(4); + info.width = stream.readUint32BE(); + info.height = stream.readUint32BE(); + stream.skip(20); + + byte rgb[768]; + stream.read(rgb, 768); + + for (uint i = 0; i < 256; i++) { + info.palette.setEntry(i, rgb[i] >> 2, rgb[i+256] >> 2, rgb[i+512] >> 2); + } + + info.bg.create(info.width, info.height, 1); + stream.read(info.bg.pixels, info.width * info.height); + } + + if (mask) { + sprintf(filename, "%s/msk/%s.msk", _partPath, mask); + if (!stream.open(filename)) + errorFileNotFound(filename); + + // NOTE: info.width and info.height are only valid if the background graphics + // have already been loaded + info.mask.create(info.width, info.height); + stream.read(info.mask.data, info.width * info.height); + } + + if (path) { + sprintf(filename, "%s/pth/%s.pth", _partPath, path); + if (!stream.open(filename)) + errorFileNotFound(filename); + + // NOTE: info.width and info.height are only valid if the background graphics + // have already been loaded + info.path.create(info.width, info.height); + stream.read(info.path.data, info.width * info.height); + } + return; } diff --git a/engines/parallaction/location.cpp b/engines/parallaction/location.cpp index 6798e72afa..001c5a8d03 100644 --- a/engines/parallaction/location.cpp +++ b/engines/parallaction/location.cpp @@ -42,116 +42,91 @@ void Parallaction::parseLocation(const char *filename) { Script *_locationScript = _disk->loadLocation(filename); _hasLocationSound = false; + // WORKAROUND: the original code erroneously incremented + // _currentLocationIndex, thus producing inconsistent + // savegames. This workaround modified the following loop + // and if-statement, so the code exactly matches the one + // in Big Red Adventure. + _currentLocationIndex = -1; + uint16 _di = 0; + while (_locationNames[_di][0] != '\0') { + if (!scumm_stricmp(_locationNames[_di], filename)) { + _currentLocationIndex = _di; + } + _di++; + } + + if (_currentLocationIndex == -1) { + strcpy(_locationNames[_numLocations], filename); + _currentLocationIndex = _numLocations; + + _numLocations++; + _locationNames[_numLocations][0] = '\0'; + _localFlags[_numLocations] = 0; + } else { + _localFlags[_currentLocationIndex] |= kFlagsVisited; // 'visited' + } + + fillBuffers(*_locationScript, true); + + printf("ciao (%s)\n", filename); + while (scumm_stricmp(_tokens[0], "ENDLOCATION")) { - if (!scumm_stricmp(_tokens[0], "LOCATION")) { - // The parameter for location is 'location.mask'. - // If mask is not present, then it is assumed - // that path & mask are encoded in the background - // bitmap, otherwise a separate .msk file exists. - - char *mask = strchr(_tokens[1], '.'); - if (mask) { - mask[0] = '\0'; - mask++; - } - - // WORKAROUND: the original code erroneously incremented - // _currentLocationIndex, thus producing inconsistent - // savegames. This workaround modified the following loop - // and if-statement, so the code exactly matches the one - // in Big Red Adventure. - _currentLocationIndex = -1; - uint16 _di = 0; - while (_locationNames[_di][0] != '\0') { - if (!scumm_stricmp(_locationNames[_di], filename)) { - _currentLocationIndex = _di; - } - _di++; - } - - if (_currentLocationIndex == -1) { - strcpy(_locationNames[_numLocations], filename); - _currentLocationIndex = _numLocations; - - _numLocations++; - _locationNames[_numLocations][0] = '\0'; - _localFlags[_numLocations] = 0; - } else { - _localFlags[_currentLocationIndex] |= kFlagsVisited; // 'visited' - } - - strcpy(_location._name, _tokens[1]); - switchBackground(_location._name, mask); - - if (_tokens[2][0] != '\0') { - _char._ani._left = atoi(_tokens[2]); - _char._ani._top = atoi(_tokens[3]); - } - - if (_tokens[4][0] != '\0') { - _char._ani._frame = atoi(_tokens[4]); - } - } - if (!scumm_stricmp(_tokens[0], "DISK")) { - _disk->selectArchive(_tokens[1]); - } - if (!scumm_stricmp(_tokens[0], "LOCALFLAGS")) { - _si = 1; // _localFlagNames[0] = 'visited' - while (_tokens[_si][0] != '\0') { - _localFlagNames->addData(_tokens[_si]); - _si++; - } - } - if (!scumm_stricmp(_tokens[0], "COMMANDS")) { - parseCommands(*_locationScript, _location._commands); - } - if (!scumm_stricmp(_tokens[0], "ACOMMANDS")) { - parseCommands(*_locationScript, _location._aCommands); - } - if (!scumm_stricmp(_tokens[0], "FLAGS")) { - if ((_localFlags[_currentLocationIndex] & kFlagsVisited) == 0) { - // only for 1st visit - _localFlags[_currentLocationIndex] = 0; - _si = 1; + printf("inst = %s\n", _tokens[0]); - do { - byte _al = _localFlagNames->lookup(_tokens[_si]); - _localFlags[_currentLocationIndex] |= 1 << (_al - 1); + bool parsed = parseLocationLine(filename, _locationScript); + if (!parsed) { + if (!scumm_stricmp(_tokens[0], "LOCALFLAGS")) { + _si = 1; // _localFlagNames[0] = 'visited' + while (_tokens[_si][0] != '\0') { + _localFlagNames->addData(_tokens[_si]); _si++; - if (scumm_stricmp(_tokens[_si], "|")) break; - _si++; - } while (true); - } - } - if (!scumm_stricmp(_tokens[0], "COMMENT")) { - _location._comment = parseComment(*_locationScript); - debugC(3, kDebugLocation, "Location comment: '%s'", _location._comment); - } - if (!scumm_stricmp(_tokens[0], "ENDCOMMENT")) { - _location._endComment = parseComment(*_locationScript); - } - if (!scumm_stricmp(_tokens[0], "ZONE")) { - parseZone(*_locationScript, _zones, _tokens[1]); - } - if (!scumm_stricmp(_tokens[0], "NODES")) { - parseWalkNodes(*_locationScript, _location._walkNodes); - } - if (!scumm_stricmp(_tokens[0], "ANIMATION")) { - parseAnimation(*_locationScript, _animations, _tokens[1]); - } - if (!scumm_stricmp(_tokens[0], "SOUND")) { - if (getPlatform() == Common::kPlatformAmiga) { - strcpy(_locationSound, _tokens[1]); - _hasLocationSound = true; - } - } - if (!scumm_stricmp(_tokens[0], "MUSIC")) { - if (getPlatform() == Common::kPlatformAmiga) - _soundMan->setMusicFile(_tokens[1]); + } + } else + if (!scumm_stricmp(_tokens[0], "COMMANDS")) { + parseCommands(*_locationScript, _location._commands); + } else + if (!scumm_stricmp(_tokens[0], "ACOMMANDS")) { + parseCommands(*_locationScript, _location._aCommands); + } else + if (!scumm_stricmp(_tokens[0], "FLAGS")) { + if ((_localFlags[_currentLocationIndex] & kFlagsVisited) == 0) { + // only for 1st visit + _localFlags[_currentLocationIndex] = 0; + _si = 1; + + do { + byte _al = _localFlagNames->lookup(_tokens[_si]); + _localFlags[_currentLocationIndex] |= 1 << (_al - 1); + + _si++; + if (scumm_stricmp(_tokens[_si], "|")) break; + _si++; + } while (true); + } + } else + if (!scumm_stricmp(_tokens[0], "COMMENT")) { + _location._comment = parseComment(*_locationScript); + } else + if (!scumm_stricmp(_tokens[0], "ENDCOMMENT")) { + _location._endComment = parseComment(*_locationScript); + } else + if (!scumm_stricmp(_tokens[0], "SOUND")) { + if (getPlatform() == Common::kPlatformAmiga) { + strcpy(_locationSound, _tokens[1]); + _hasLocationSound = true; + } + } else + if (!scumm_stricmp(_tokens[0], "MUSIC")) { + if (getPlatform() == Common::kPlatformAmiga) + _soundMan->setMusicFile(_tokens[1]); + } else + error("unknown keyword '%s' in location '%s'", _tokens[0], filename); } + fillBuffers(*_locationScript, true); } @@ -245,11 +220,9 @@ void Parallaction::freeBackground() { } -void Parallaction::setBackground(const char *background, const char *mask, const char *path) { - - freeBackground(); +void Parallaction::setBackground(const char* name, const char* mask, const char* path) { - _disk->loadScenery(*_backgroundInfo, background, mask, path); + _disk->loadScenery(*_backgroundInfo, name, mask, path); _gfx->setPalette(_backgroundInfo->palette); _gfx->_palette.clone(_backgroundInfo->palette); @@ -264,7 +237,6 @@ void Parallaction::setBackground(const char *background, const char *mask, const return; } - void Parallaction::showLocationComment(const char *text, bool end) { _gfx->setFont(_dialogueFont); diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 6c040c9774..8549cba24f 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -310,6 +310,7 @@ public: void waitTime(uint32 t); void parseLocation(const char *filename); + virtual bool parseLocationLine(const char *filename, Script *script) = 0; void changeCursor(int32 index); void showCursor(bool visible); void changeCharacter(const char *name); @@ -512,6 +513,7 @@ public: virtual void callFunction(uint index, void* parm); void renderLabel(Graphics::Surface *cnv, char *text); void setMousePointer(int16 index); + virtual bool parseLocationLine(const char *filename, Script *script); public: @@ -579,6 +581,7 @@ public: public: typedef void (Parallaction_br::*Callable)(void*); virtual void callFunction(uint index, void* parm); + virtual bool parseLocationLine(const char *filename, Script *script); public: Table *_countersNames; diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index f6dd1aee45..82dfd96f54 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -343,5 +343,83 @@ void Parallaction_br::startPart() { } +void skip(Script* script, const char* endToken) { + + while (scumm_stricmp(_tokens[0], endToken)) { + fillBuffers(*script, true); + } + +} + +bool Parallaction_br::parseLocationLine(const char *filename, Script *script) { + + bool parsed = true; + bool flip = false; + int nextToken = 0; + + if (!scumm_stricmp(_tokens[0], "LOCATION")) { + + strcpy(_location._name, _tokens[1]); + _disk->loadScenery(*_backgroundInfo, _location._name, NULL, NULL); + _gfx->setBackground(&_backgroundInfo->bg); + _gfx->_palette.clone(_backgroundInfo->palette); + _gfx->setPalette(_backgroundInfo->palette); + + if (!scumm_stricmp("flip", _tokens[2])) { + flip = true; + nextToken = 3; + } else { + nextToken = 2; + } + + if (_tokens[nextToken][0] != '\0') { + _char._ani._left = atoi(_tokens[nextToken]); + nextToken++; + _char._ani._top = atoi(_tokens[nextToken]); + nextToken++; + } + + if (_tokens[nextToken][0] != '\0') { + _char._ani._frame = atoi(_tokens[nextToken]); + } + } else + if (!scumm_stricmp(_tokens[0], "IFCHAR")) { + skip(script, "ENDIF"); + } else + if (!scumm_stricmp(_tokens[0], "CHARACTER")) { + + } else + if (!scumm_stricmp(_tokens[0], "MASK")) { + _disk->loadScenery(*_backgroundInfo, NULL, _tokens[1], NULL); + _gfx->setMask(&_backgroundInfo->mask); + + _gfx->_bgLayers[0] = atoi(_tokens[2]); + _gfx->_bgLayers[1] = atoi(_tokens[3]); + _gfx->_bgLayers[2] = atoi(_tokens[4]); + } else + if (!scumm_stricmp(_tokens[0], "PATH")) { + _disk->loadScenery(*_backgroundInfo, NULL, NULL, _tokens[1]); + _pathBuffer = &_backgroundInfo->path; + } else + if (!scumm_stricmp(_tokens[0], "DISK")) { + // + } else + if (!scumm_stricmp(_tokens[0], "ESCAPE")) { + skip(script, "endcommands"); + } else + if (!scumm_stricmp(_tokens[0], "ZETA")) { + // + } else + if (!scumm_stricmp(_tokens[0], "ZONE")) { + skip(script, "endzone"); + } else + if (!scumm_stricmp(_tokens[0], "ANIMATION")) { + skip(script, "endanimation"); + } else + parsed = false; + + return parsed; +} + } // namespace Parallaction diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index 6dcae1bdc8..38e2d999ff 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -199,6 +199,49 @@ int Parallaction_ns::go() { return 0; } +bool Parallaction_ns::parseLocationLine(const char *filename, Script *script) { + bool parsed = true; + + if (!scumm_stricmp(_tokens[0], "LOCATION")) { + // The parameter for location is 'location.mask'. + // If mask is not present, then it is assumed + // that path & mask are encoded in the background + // bitmap, otherwise a separate .msk file exists. + + char *mask = strchr(_tokens[1], '.'); + if (mask) { + mask[0] = '\0'; + mask++; + } + + strcpy(_location._name, _tokens[1]); + switchBackground(_location._name, mask); + + if (_tokens[2][0] != '\0') { + _char._ani._left = atoi(_tokens[2]); + _char._ani._top = atoi(_tokens[3]); + } + + if (_tokens[4][0] != '\0') { + _char._ani._frame = atoi(_tokens[4]); + } + } else + if (!scumm_stricmp(_tokens[0], "DISK")) { + _disk->selectArchive(_tokens[1]); + } else + if (!scumm_stricmp(_tokens[0], "NODES")) { + parseWalkNodes(*script, _location._walkNodes); + } else + if (!scumm_stricmp(_tokens[0], "ZONE")) { + parseZone(*script, _zones, _tokens[1]); + } else + if (!scumm_stricmp(_tokens[0], "ANIMATION")) { + parseAnimation(*script, _animations, _tokens[1]); + } else + parsed = false; + + return parsed; +} } // namespace Parallaction diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp index 44aae6c1cc..d786cc6487 100644 --- a/engines/parallaction/parser.cpp +++ b/engines/parallaction/parser.cpp @@ -48,7 +48,7 @@ char *Script::readLine(char *buf, size_t bufSize) { v2 = _input->readSByte(); - if (v2 == 0xA || _input->eos()) break; + if (v2 == 0xA || v2 == 0xD || _input->eos()) break; if (!_input->eos() && _si < bufSize) buf[_si] = v2; } -- cgit v1.2.3