aboutsummaryrefslogtreecommitdiff
path: root/engines/cryomni3d/wam_parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/cryomni3d/wam_parser.cpp')
-rw-r--r--engines/cryomni3d/wam_parser.cpp216
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