diff options
Diffstat (limited to 'engines/cryomni3d/wam_parser.cpp')
-rw-r--r-- | engines/cryomni3d/wam_parser.cpp | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/engines/cryomni3d/wam_parser.cpp b/engines/cryomni3d/wam_parser.cpp new file mode 100644 index 0000000000..a27e3ab69e --- /dev/null +++ b/engines/cryomni3d/wam_parser.cpp @@ -0,0 +1,216 @@ +/* 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 "common/stream.h" + +#include "engines/cryomni3d/wam_parser.h" +#include "engines/cryomni3d/omni3d.h" + +namespace CryOmni3D { + +void WAMParser::loadStream(Common::ReadStream &stream) { + char str[16]; + + _places.clear(); + + stream.readByte(); + stream.readByte(); + stream.read(str, 16); + stream.readUint32LE(); + + unsigned int nPlaces = stream.readByte(); + //debug("nPlaces = %u", nPlaces); + for (unsigned int i = 0; i < nPlaces; i++) { + Place place; + unsigned int nWarps = stream.readByte(); + //debug("nWarps = %u", nWarps); + for (unsigned int k = 0; k < 8; k++) { + stream.read(str, 16); + //debug("Warp: %.16s", str); + if (nWarps > 0) { + place.warps.push_back(str); + nWarps--; + } + } + place.placeId = stream.readUint32LE(); + // Normally placeId should be unique but it's not always the case + // In original game the last place is considered but we try to be efficient and stop at the first place in findPlaceById + // Let's be a little less efficient at startup by removing duplicates + Place *oldPlace = findPlaceById_(place.placeId); + if (oldPlace) { + debug("Found duplicate place %u at %u, removing it", place.placeId, + (unsigned int)(oldPlace - _places.begin())); + _places.erase(oldPlace); + } + //debug("nPlaceId = %u", place.placeId); + stream.readUint32LE(); + unsigned int nTransitions = stream.readByte(); + //debug("nTransitions = %u", nTransitions); + unsigned int nZones = stream.readByte(); + //debug("nZones = %u", nZones); + for (unsigned int j = 0; j < nTransitions; j++) { + Transition trans; + stream.readUint32LE(); + unsigned int nAnimations = stream.readByte(); + for (unsigned int k = 0; k < 8; k++) { + stream.read(str, 16); + if (nAnimations > 0) { + trans.animations.push_back(str); + nAnimations--; + } + } + stream.readUint32LE(); + trans.dstId = stream.readUint32LE(); + stream.readByte(); + trans.srcAlpha = stream.readDoubleLE(); + trans.srcBeta = stream.readDoubleLE(); + trans.dstAlpha = stream.readDoubleLE(); + trans.dstBeta = stream.readDoubleLE(); + place.transitions.push_back(trans); + } + for (unsigned int j = 0; j < nZones; j++) { + Zone zone; + zone.zoneId = stream.readSint32LE(); + zone.rct.left = stream.readSint32LE(); + zone.rct.top = stream.readSint32LE(); + zone.rct.setWidth(stream.readSint32LE()); + zone.rct.setHeight(stream.readSint32LE()); + zone.action = stream.readSint32LE(); + place.zones.push_back(zone); + } + _places.push_back(place); + } +} + +const Place *WAMParser::findPlaceById(unsigned int placeId) const { + for (Common::Array<Place>::const_iterator it = _places.begin(); it != _places.end(); it++) { + if (it->placeId == placeId) { + return it; + } + } + return nullptr; +} + +Place *WAMParser::findPlaceById_(unsigned int placeId) { + for (Common::Array<Place>::iterator it = _places.begin(); it != _places.end(); it++) { + if (it->placeId == placeId) { + return it; + } + } + return nullptr; +} + +void Place::setupWarpConstraints(Omni3DManager &omni3d) const { + int16 iAlphaMin, iAlphaMax; + bool alphaConstraint = false; + + omni3d.clearConstraints(); + for (Common::Array<Zone>::const_iterator it = zones.begin(); it != zones.end(); it++) { + if (it->action == 100000) { + int16 aMin = it->rct.left; + if (aMin < 0) { + aMin += 2048; + } + int16 aMax = aMin + it->rct.width(); + if (aMax > 2048) { + aMax -= 2048; + } + // debug("x1=%d x2=%d", aMin, aMax); + if (aMax < aMin) { + int16 tmp = aMax; + aMax = aMin; + aMin = tmp; + } + if (alphaConstraint) { + if (aMin < iAlphaMax && aMax > iAlphaMax) { + iAlphaMax = aMax; + } + if (aMin < iAlphaMin && aMax > iAlphaMin) { + iAlphaMin = aMin; + } + } else { + iAlphaMin = aMin; + iAlphaMax = aMax; + alphaConstraint = true; + } + } else if (it->action == 200000) { + double betaMin = ((int)it->rct.bottom - (768 / 2)) / 768. * M_PI; + omni3d.setBetaMinConstraint(betaMin); + } else if (it->action == 300000) { + double betaMax = ((int)it->rct.top - (768 / 2)) / 768. * M_PI; + omni3d.setBetaMaxConstraint(betaMax); + } + } + if (alphaConstraint) { + double alphaMin = (1 - iAlphaMin / 2048.) * M_PI * 2.; + alphaMin += 75. / 180. * M_PI_2; + if (alphaMin < 0.) { + alphaMin += M_PI * 2.; + } else if (alphaMin > M_PI * 2.) { + alphaMin -= M_PI * 2.; + } + double alphaMax = (1 - iAlphaMax / 2048.) * M_PI * 2.; + alphaMax -= 75. / 180. * M_PI_2; + if (alphaMax < 0.) { + alphaMax += M_PI * 2.; + } else if (alphaMax > M_PI * 2.) { + alphaMax -= M_PI * 2.; + } + omni3d.setAlphaConstraints(alphaMin, alphaMax); + } +} + +unsigned int Place::hitTest(const Common::Point &point) const { + for (Common::Array<Zone>::const_iterator it = zones.begin(); it != zones.end(); it++) { + if (it->action) { + if (it->rct.contains(point)) { + return it->action; + } + if (it->rct.left < 0) { + Common::Rect rct = it->rct; + rct.translate(2048, 0); + if (rct.contains(point)) { + return it->action; + } + } else if (it->rct.right > 2048) { + Common::Rect rct = it->rct; + rct.translate(-2048, 0); + if (rct.contains(point)) { + return it->action; + } + } + } + } + return 0; +} + +const Transition *Place::findTransition(unsigned int nextPlaceId) const { + for (Common::Array<Transition>::const_iterator it = transitions.begin(); it != transitions.end(); + it++) { + if (it->dstId == nextPlaceId) { + return it; + } + } + return nullptr; +} + +} // End of namespace CryOmni3D |