From ac9cd1f00a28b09dd0202c90a2fe023bc8cba525 Mon Sep 17 00:00:00 2001 From: Matthew Stewart Date: Wed, 18 Jul 2018 23:53:21 -0400 Subject: STARTREK: Implement fixed-point decimal class --- engines/startrek/awaymission.cpp | 26 +++---- engines/startrek/common.h | 7 +- engines/startrek/fixedint.h | 152 +++++++++++++++++++++++++++++++++++++++ engines/startrek/object.h | 1 + engines/startrek/room.cpp | 4 +- engines/startrek/room.h | 13 ++-- engines/startrek/saveload.cpp | 10 +-- engines/startrek/space.cpp | 64 ++++++++++++----- engines/startrek/space.h | 115 +++++++++++++++++++++++++---- engines/startrek/startrek.cpp | 112 +++++++++++++++++------------ engines/startrek/startrek.h | 24 +++++-- 11 files changed, 417 insertions(+), 111 deletions(-) create mode 100644 engines/startrek/fixedint.h diff --git a/engines/startrek/awaymission.cpp b/engines/startrek/awaymission.cpp index e086bca045..94ee86993c 100644 --- a/engines/startrek/awaymission.cpp +++ b/engines/startrek/awaymission.cpp @@ -105,9 +105,9 @@ void StarTrekEngine::loadRoom(const Common::String &missionName, int roomIndex) actorFunc1(); initActors(); - double num = _room->getVar0c() - _room->getVar0a(); - double den = _room->getVar06() - _room->getVar08() + 1; - _playerActorScale = (int32)(num * 256 / den); + Fixed16 num = _room->getMaxScale() - _room->getMinScale(); + int16 den = _room->getMaxY() - _room->getMinY() + 1; + _playerActorScale = Fixed32(num) / den; // TODO: RDF vars 1e/1f and 20/21; relates to BAN files? @@ -446,21 +446,21 @@ void StarTrekEngine::unloadRoom() { * further up (away) the object is, the smaller it is. */ int StarTrekEngine::loadActorAnimWithRoomScaling(int actorIndex, const Common::String &animName, int16 x, int16 y) { - uint16 scale = getActorScaleAtPosition(y); + Fixed16 scale = getActorScaleAtPosition(y); return loadActorAnim(actorIndex, animName, x, y, scale); } -uint16 StarTrekEngine::getActorScaleAtPosition(int16 y) { - int16 var06 = _room->getVar06(); - int16 var08 = _room->getVar08(); - int16 var0a = _room->getVar0a(); +Fixed16 StarTrekEngine::getActorScaleAtPosition(int16 y) { + int16 maxY = _room->getMaxY(); + int16 minY = _room->getMinY(); + Fixed16 minScale = _room->getMinScale(); - if (var06 < y) - y = var06; - if (var08 > y) - y = var08; + if (y > maxY) + y = maxY; + if (y < minY) + y = minY; - return ((_playerActorScale * (y - var08)) >> 8) + var0a; + return Fixed16(_playerActorScale * (y - minY)) + minScale; } SharedPtr StarTrekEngine::getRoom() { diff --git a/engines/startrek/common.h b/engines/startrek/common.h index d76ef66c28..290772f4a1 100644 --- a/engines/startrek/common.h +++ b/engines/startrek/common.h @@ -23,6 +23,7 @@ #define STARTREK_COMMON_H #include "common/scummsys.h" +#include "common/textconsole.h" namespace Common { struct Rect; @@ -41,12 +42,6 @@ Common::Rect getRectEncompassing(Common::Rect r1, Common::Rect r2); void serializeRect(Common::Rect rect, Common::Serializer &ser); -// Fixed-point (16.16) number -typedef int32 Fixed32; - -// Fixed-point (8.8) number -typedef int16 Fixed16; - } #endif diff --git a/engines/startrek/fixedint.h b/engines/startrek/fixedint.h new file mode 100644 index 0000000000..a91e6b33d9 --- /dev/null +++ b/engines/startrek/fixedint.h @@ -0,0 +1,152 @@ +/* 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 STARTREK_FIXEDINT_H +#define STARTREK_FIXEDINT_H + +#include "common/serializer.h" + +#include "startrek/common.h" + +namespace StarTrek { + +/** + * Signed fixed-point number. + */ +template +class TFixedInt : Common::Serializable { + const static int max = (1 << (totalBits - decimalBits - 1)) - 1; + const static int min = -max - 1; + + T val; + +public: + static TFixedInt fromRaw(T raw) { + TFixedInt ret; + ret.val = raw; + return ret; + } + + TFixedInt() : val(0) {} + TFixedInt(double d) { + assert(d >= min && d <= max); // FIXME: downgrade this to a warning? + val = (T)(d * (1 << decimalBits)); + } + + /** + * Constructor from other fixed-point formats. + */ + template + TFixedInt(const TFixedInt &fi) { + int diff = otherDB - decimalBits; + if (otherDB >= decimalBits) + val = fi.raw() >> diff; + else + val = fi.raw() << (-diff); + } + + T raw() const { + return val; + } + + int16 toInt() const { + return val >> decimalBits; + } + + double toDouble() const { + return ((double)val) / (1 << decimalBits); + } + + /** + * Multiplication with an int, with the result being an int. + */ + int32 multToInt(int32 i) { + return ((val * i) << (totalBits - decimalBits)) >> totalBits; + } + + /** + * Multiplication with an int, with the result being the same type. + */ + TFixedInt operator*(int32 i) const { + return fromRaw(val * i); + } + /** + * Division with an int, with the result being the same type. + */ + TFixedInt operator/(int32 i) const { + return fromRaw(val / i); + } + TFixedInt operator+(const TFixedInt &f) const { + return fromRaw(val + f.val); + } + TFixedInt operator-(const TFixedInt &f) const { + return fromRaw(val - f.val); + } + + void operator+=(const TFixedInt &f) { + val += f.val; + } + void operator-=(const TFixedInt &f) { + val -= f.val; + } + + bool operator==(double d) const { + return toDouble() == d; + } + bool operator!=(double d) const { + return toDouble() != d; + } + bool operator<(double d) const { + return toDouble() < d; + } + bool operator<=(double d) const { + return toDouble() <= d; + } + + void saveLoadWithSerializer(Common::Serializer &ser) { + if (totalBits == 16) + ser.syncAsSint16LE(val); + else if (totalBits == 32) + ser.syncAsSint32LE(val); + else + error("Unsupported bit size for TFixedInt"); + } +}; + +template +int32 operator*(const int16 lhs, const TFixedInt &rhs) { + return rhs * lhs; +} + + +// Fixed-point (2.14) number (between -1 and 1) +typedef TFixedInt Fixed14; + +// Fixed-point (8.8) number +typedef TFixedInt Fixed16; + +// Fixed-point (16.16) number +typedef TFixedInt Fixed32; + +} + +#endif diff --git a/engines/startrek/object.h b/engines/startrek/object.h index 3a2dc335ef..e10a0f637f 100644 --- a/engines/startrek/object.h +++ b/engines/startrek/object.h @@ -24,6 +24,7 @@ #define STARTREK_OBJECT_H #include "startrek/common.h" +#include "startrek/fixedint.h" #include "startrek/items.h" #include "startrek/sprite.h" diff --git a/engines/startrek/room.cpp b/engines/startrek/room.cpp index 4ec703f69d..a9f83118b6 100644 --- a/engines/startrek/room.cpp +++ b/engines/startrek/room.cpp @@ -210,7 +210,7 @@ void Room::loadActorAnim(int actorIndex, Common::String anim, int16 x, int16 y, if (actorIndex >= 0 && actorIndex < SCALED_ACTORS_END) _vm->loadActorAnimWithRoomScaling(actorIndex, anim, x, y); else - _vm->loadActorAnim(actorIndex, anim, x, y, 256); + _vm->loadActorAnim(actorIndex, anim, x, y, 1.0); if (finishedAnimActionParam != 0) { actor->triggerActionWhenAnimFinished = true; @@ -231,7 +231,7 @@ void Room::loadActorAnimC(int actorIndex, Common::String anim, int16 x, int16 y, if (actorIndex >= 0 && actorIndex < SCALED_ACTORS_END) _vm->loadActorAnimWithRoomScaling(actorIndex, anim, x, y); else - _vm->loadActorAnim(actorIndex, anim, x, y, 256); + _vm->loadActorAnim(actorIndex, anim, x, y, 1.0); if (funcPtr != nullptr) { actor->triggerActionWhenAnimFinished = true; diff --git a/engines/startrek/room.h b/engines/startrek/room.h index 1442e90162..434ff76eb2 100644 --- a/engines/startrek/room.h +++ b/engines/startrek/room.h @@ -27,6 +27,7 @@ #include "common/ptr.h" #include "common/str.h" +#include "startrek/fixedint.h" #include "startrek/startrek.h" #include "startrek/text.h" @@ -60,11 +61,13 @@ public: // Helper stuff for RDF access uint16 readRdfWord(int offset); - // Scale-related stuff (rename these later) - uint16 getVar06() { return readRdfWord(0x06); } - uint16 getVar08() { return readRdfWord(0x08); } - uint16 getVar0a() { return readRdfWord(0x0a); } - uint16 getVar0c() { return readRdfWord(0x0c); } + // Scale-related stuff; at the "min Y" position or below, the crewmembers have + // "minimum" scale; that value rises to the "max scale" value by the time they reach + // the "max Y" value. + uint16 getMaxY() { return readRdfWord(0x06); } + uint16 getMinY() { return readRdfWord(0x08); } + Fixed16 getMinScale() { return Fixed16::fromRaw(readRdfWord(0x0a)); } + Fixed16 getMaxScale() { return Fixed16::fromRaw(readRdfWord(0x0c)); } // words 0x0e and 0x10 in RDF file are pointers to start and end of event code. // That code is instead rewritten on a per-room basis. diff --git a/engines/startrek/saveload.cpp b/engines/startrek/saveload.cpp index 443d4a5446..3d1a1aad3f 100644 --- a/engines/startrek/saveload.cpp +++ b/engines/startrek/saveload.cpp @@ -256,7 +256,7 @@ bool StarTrekEngine::saveOrLoadGameData(Common::SeekableReadStream *in, Common:: a->sprite.saveLoadWithSerializer(ser); ser.syncBytes((byte *)a->bitmapFilename, 10); - ser.syncAsUint16LE(a->scale); + a->scale.saveLoadWithSerializer(ser); // Can't save "animFile" (will be reloaded) ser.syncAsUint16LE(a->numAnimFrames); ser.syncAsUint16LE(a->animFrame); @@ -274,10 +274,10 @@ bool StarTrekEngine::saveOrLoadGameData(Common::SeekableReadStream *in, Common:: ser.syncAsUint16LE(a->field76); ser.syncAsSint16LE(a->iwSrcPosition); ser.syncAsSint16LE(a->iwDestPosition); - ser.syncAsSint32LE(a->granularPosX); - ser.syncAsSint32LE(a->granularPosY); - ser.syncAsSint32LE(a->speedX); - ser.syncAsSint32LE(a->speedY); + a->granularPosX.saveLoadWithSerializer(ser); + a->granularPosY.saveLoadWithSerializer(ser); + a->speedX.saveLoadWithSerializer(ser); + a->speedY.saveLoadWithSerializer(ser); ser.syncAsSint16LE(a->dest.x); ser.syncAsSint16LE(a->dest.y); ser.syncAsUint16LE(a->field90); diff --git a/engines/startrek/space.cpp b/engines/startrek/space.cpp index 1171952ed4..a4d09690f8 100644 --- a/engines/startrek/space.cpp +++ b/engines/startrek/space.cpp @@ -26,8 +26,8 @@ namespace StarTrek { void StarTrekEngine::initStarfieldPosition() { - memset(&_starfieldPosition, 0, sizeof(_starfieldPosition)); - // TODO: matrix initialization + _starfieldPosition = Point3(0, 0, 0); + _someMatrix = initMatrix(); } void StarTrekEngine::initStarfield(int16 x, int16 y, int16 width, int16 height, int16 arg8) { @@ -45,13 +45,35 @@ void StarTrekEngine::initStarfield(int16 x, int16 y, int16 width, int16 height, _starfieldPointDivisor = 150; } +void StarTrekEngine::addR3(R3 *r3) { + for (int i = 0; i < NUM_SPACE_OBJECTS; i++) { + if (_r3List[i] == nullptr) { + _r3List[i] = r3; + return; + } + } + + error("addR3: out of shapes."); +} + +void StarTrekEngine::delR3(R3 *r3) { + for (int i = 0; i < NUM_SPACE_OBJECTS; i++) { + if (_r3List[i] == r3) { + _r3List[i] = nullptr; + r3->field1e = 0; + return; + } + } + + error("delR3: shape not found."); +} + void StarTrekEngine::clearStarfieldPixels() { _gfx->fillBackgroundRect(_starfieldRect, 0); } void StarTrekEngine::drawStarfield() { // TODO: make these class variables - Point3W starPositionWeightings[] = {{0x4000, 0, 0}, {0, 0x4000, 0}, {0, 0, 0x4000}}; float flt_50898 = 50.0; // ? int16 var28 = ((_starfieldXVar2 * 3) >> 1); @@ -72,12 +94,12 @@ void StarTrekEngine::drawStarfield() { int16 var4 = getRandomWord() / var28 - xvar; int16 var6 = getRandomWord() / var2a - yvar; Point3 point = constructPoint3ForStarfield(var4, var6, var8); - star->pos = applyPointWeightings(starPositionWeightings, point) + _starfieldPosition; + star->pos = matrixMult(_starPositionMatrix, point) + _starfieldPosition; star->active = true; } Point3 p = star->pos - _starfieldPosition; - Point3 point2 = applyPointWeightings2(p, starPositionWeightings); + Point3 point2 = matrixMult(p, _starPositionMatrix); if (point2.z > flt_50898 && point2.z < 0x3fff && abs(point2.x) < point2.z && abs(point2.y) < point2.z) { @@ -111,7 +133,7 @@ void StarTrekEngine::drawStarfield() { void StarTrekEngine::updateStarfieldAndShips(bool arg0) { _starfieldSprite.bitmapChanged = true; - // sub_24b74(...); + _starPositionMatrix = _someMatrix.invert(); clearStarfieldPixels(); drawStarfield(); @@ -127,28 +149,32 @@ Point3 StarTrekEngine::constructPoint3ForStarfield(int16 x, int16 y, int16 z) { return point; } -Point3 StarTrekEngine::applyPointWeightings(Point3W *weight, const Point3 &point) { +Point3 StarTrekEngine::matrixMult(const Matrix &weight, const Point3 &point) { int32 ret[3]; for (int i = 0; i < 3; i++) { - ret[i] = weight[i].x * (point.x & 0xffff) + weight[i].y * (point.y & 0xffff) + weight[i].z * (point.z & 0xffff); - ret[i] <<= 2; + ret[i] = weight[i][0].multToInt(point.x & 0xffff) + weight[i][1].multToInt(point.y & 0xffff) + weight[i][2].multToInt(point.z & 0xffff); } Point3 p; - p.x = ret[0] >> 16; - p.y = ret[1] >> 16; - p.z = ret[2] >> 16; + p.x = ret[0]; + p.y = ret[1]; + p.z = ret[2]; return p; } -Point3 StarTrekEngine::applyPointWeightings2(const Point3 &point, Point3W *weight) { +Point3 StarTrekEngine::matrixMult(const Point3 &point, const Matrix &weight) { Point3 p = Point3(); - p.x = (weight[0].x * (point.x & 0xffff) + weight[1].x * (point.y & 0xffff) + weight[2].x * (point.z & 0xffff)) << 2; - p.y = (weight[0].y * (point.x & 0xffff) + weight[1].y * (point.y & 0xffff) + weight[2].y * (point.z & 0xffff)) << 2; - p.z = (weight[0].z * (point.x & 0xffff) + weight[1].z * (point.y & 0xffff) + weight[2].z * (point.z & 0xffff)) << 2; - p.x >>= 16; - p.y >>= 16; - p.z >>= 16; + p.x = (weight[0][0].multToInt(point.x & 0xffff) + weight[1][0].multToInt(point.y & 0xffff) + weight[2][0].multToInt(point.z & 0xffff)); + p.y = (weight[0][1].multToInt(point.x & 0xffff) + weight[1][1].multToInt(point.y & 0xffff) + weight[2][1].multToInt(point.z & 0xffff)); + p.z = (weight[0][2].multToInt(point.x & 0xffff) + weight[1][2].multToInt(point.y & 0xffff) + weight[2][2].multToInt(point.z & 0xffff)); return p; } +Matrix StarTrekEngine::initMatrix() { + Matrix mat; + mat[0][0] = 1; + mat[1][1] = 1; + mat[2][2] = 1; + return mat; +} + } diff --git a/engines/startrek/space.h b/engines/startrek/space.h index f5d08e5d1e..a9c6bdea93 100644 --- a/engines/startrek/space.h +++ b/engines/startrek/space.h @@ -1,32 +1,113 @@ -// Pseudo-3D structs +/* 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. -struct Point3 { - int32 x; - int32 y; - int32 z; + * 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. - Point3 operator+(const Point3 &p) const { - Point3 p2; + * 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 STARTREK_SPACE_H +#define STARTREK_SPACE_H + +#include "fixedint.h" + +namespace StarTrek { + +class FileStream; + +template +struct TPoint { + T x; + T y; + T z; + + TPoint() : x(0), y(0), z(0) {} + TPoint(T _x, T _y, T _z) : x(_x), y(_y), z(_z) {} + + TPoint operator+(const TPoint &p) const { + TPoint p2; p2.x = x + p.x; p2.y = y + p.y; p2.z = z + p.z; return p2; } - Point3 operator-(const Point3 &p) const { - Point3 p2; + TPoint operator-(const TPoint &p) const { + TPoint p2; p2.x = x - p.x; p2.y = y - p.y; p2.z = z - p.z; return p2; } + T &operator[](int i) { + if (i == 0) + return x; + else if (i == 1) + return y; + else if (i == 2) + return z; + assert(false); + } + T operator[](int i) const { + if (i == 0) + return x; + else if (i == 1) + return y; + else if (i == 2) + return z; + assert(false); + } }; -struct Point3W { - int16 x; - int16 y; - int16 z; +typedef TPoint Point3; +typedef TPoint Point3W; + + +template +struct TMatrix { +private: + T m[3]; + +public: + TMatrix() {} + TMatrix(const TMatrix &mat) { + m[0] = mat.m[0]; + m[1] = mat.m[1]; + m[2] = mat.m[2]; + } + T &operator[](int i) { + return m[i]; + }; + T operator[](int i) const { + return m[i]; + }; + + TMatrix invert() { + TMatrix ret; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + ret[i][j] = m[j][i]; + } + } + return ret; + } }; +typedef TMatrix Matrix; + struct Star { bool active; Point3 pos; @@ -37,6 +118,10 @@ struct Star { struct R3 { Point3 pos; // 0x0 int16 field1e; // 0x1e + int16 field20; // 0x20 + int16 field22; // 0x22 + int16 field24; // 0x24 + SharedPtr shpFile; // 0x68 }; // Maximum number of stars visible at once in the starfields @@ -44,3 +129,7 @@ struct R3 { // Maximum number of R3 objects in space at once #define NUM_SPACE_OBJECTS 0x30 + +} + +#endif diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp index ab1e3c7ee5..9adba5fd85 100644 --- a/engines/startrek/startrek.cpp +++ b/engines/startrek/startrek.cpp @@ -217,6 +217,10 @@ void StarTrekEngine::playIntro() { _starfieldSprite.bitmap = fakeStarfieldBitmap; initStarfieldSprite(&_starfieldSprite, fakeStarfieldBitmap, _starfieldRect); + //delR3(&_enterpriseR3); // TODO: uncomment + + R3 planetR3 = R3(); + // TODO: remainder of starfield initialization _gfx->clearScreenAndPriBuffer(); @@ -312,8 +316,26 @@ void StarTrekEngine::playIntro() { loadSubtitleSprite(1, &subtitleSprite); break; - case 42: + case 42: // Enterprise moves toward camera loadSubtitleSprite(-1, &subtitleSprite); + addR3(&_enterpriseR3); + _enterpriseR3.field1e = 2; + initIntroR3ObjectToMove(&_enterpriseR3, 330, 5000, 0, 0, 18); + break; + + case 60: // Enterprise moves away from camera + initIntroR3ObjectToMove(&_enterpriseR3, 0, 0, 30, 5000, 6); + break; + + case 66: // Cut to scene with planet + loadSubtitleSprite(2, &subtitleSprite); + planetR3.field22 = 2000; + planetR3.field24 = 10000 / _starfieldPointDivisor; + planetR3.shpFile = loadFile("planet.shp"); + initIntroR3ObjectToMove(&planetR3, 6, 10000, 6, 10000, 0); + addR3(&planetR3); + initIntroR3ObjectToMove(&_enterpriseR3, -15, 250, 15, 500, 18); + starfieldZoomSpeed = 0; break; case 378: @@ -344,6 +366,11 @@ void StarTrekEngine::playIntro() { // TODO: the rest } +void StarTrekEngine::initIntroR3ObjectToMove(R3 *r3, int16 srcAngle, int16 srcDepth, int16 destAngle, int16 destDepth, int16 ticks) { + srcAngle = (srcAngle << 9) / 180; + destAngle = (destAngle << 9) / 180; +} + void StarTrekEngine::loadSubtitleSprite(int index, Sprite *sprite) { if (_showSubtitles) { if (index == -1) @@ -379,25 +406,25 @@ void StarTrekEngine::runTransportSequence(const Common::String &name) { Common::String filename = getCrewmanAnimFilename(i, name); int x = crewmanTransportPositions[i][0]; int y = crewmanTransportPositions[i][1]; - loadActorAnim(i, filename, x, y, 256); + loadActorAnim(i, filename, x, y, 1.0); _actorList[i].animationString[0] = '\0'; } if (_missionToLoad.equalsIgnoreCase("feather") && name[4] == 'b') { - loadActorAnim(9, "qteleb", 0x61, 0x79, 0x100); + loadActorAnim(9, "qteleb", 0x61, 0x79, 1.0); } else if (_missionToLoad.equalsIgnoreCase("trial")) { if (name[4] == 'd') { - loadActorAnim(9, "qteled", 0x61, 0x79, 0x100); + loadActorAnim(9, "qteled", 0x61, 0x79, 1.0); } /* TODO else if (word_51156 >= 3) { - loadActorAnim(9, "qteleb", 0x61, 0x79, 0x100); + loadActorAnim(9, "qteleb", 0x61, 0x79, 1.0); } */ } - loadActorAnim(8, "transc", 0, 0, 0x100); + loadActorAnim(8, "transc", 0, 0, 1.0); // TODO: redraw mouse and sprite_52c4e? @@ -570,7 +597,7 @@ bool StarTrekEngine::actorWalkToPosition(int actorIndex, const Common::String &a if (directPathExists(srcX, srcY, destX, destY)) { chooseActorDirectionForWalking(actor, srcX, srcY, destX, destY); - updateActorPositionWhileWalking(actor, (actor->granularPosX + 0x8000) >> 16, (actor->granularPosY + 0x8000) >> 16); + updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt()); return true; } else { @@ -590,7 +617,7 @@ bool StarTrekEngine::actorWalkToPosition(int actorIndex, const Common::String &a else { Common::Point iwSrc = _iwFile->_keyPositions[actor->iwSrcPosition]; chooseActorDirectionForWalking(actor, srcX, srcY, iwSrc.x, iwSrc.y); - updateActorPositionWhileWalking(actor, (actor->granularPosX + 0x8000) >> 16, (actor->granularPosY + 0x8000) >> 16); + updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt()); return true; } } @@ -660,7 +687,7 @@ void StarTrekEngine::updateActorAnimations() { if (actor->field90 != 0) { Sprite *sprite = &actor->sprite; int loops; - if (getActorScaleAtPosition((actor->granularPosY + 0x8000) >> 16) < 0xa0) + if (getActorScaleAtPosition((actor->granularPosY + 0.5).toInt()) < 0.625) loops = 1; else loops = 2; @@ -668,11 +695,11 @@ void StarTrekEngine::updateActorAnimations() { if (actor->field90 == 0) break; actor->field90--; - uint32 newX = actor->granularPosX + actor->speedX; - uint32 newY = actor->granularPosY + actor->speedY; + Fixed32 newX = actor->granularPosX + actor->speedX; + Fixed32 newY = actor->granularPosY + actor->speedY; if ((actor->field90 & 3) == 0) { sprite->bitmap.reset(); - updateActorPositionWhileWalking(actor, (newX + 0x8000) >> 16, (newY + 0x8000) >> 16); + updateActorPositionWhileWalking(actor, (newX + 0.5).toInt(), (newY + 0.5).toInt()); actor->field92++; } @@ -689,7 +716,7 @@ void StarTrekEngine::updateActorAnimations() { } actor->sprite.bitmap.reset(); - updateActorPositionWhileWalking(actor, (actor->granularPosX + 0x8000) >> 16, (actor->granularPosY + 0x8000) >> 16); + updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt()); initStandAnim(i); } else { // actor->iwSrcPosition != -1 @@ -834,7 +861,7 @@ void StarTrekEngine::initStandAnim(int actorIndex) { else // Default to facing south animName = Common::String(actor->animationString) + 's'; - uint16 scale = getActorScaleAtPosition(actor->pos.y); + Fixed16 scale = getActorScaleAtPosition(actor->pos.y); loadActorAnim(actorIndex, animName, actor->pos.x, actor->pos.y, scale); actor->animType = 0; } @@ -863,8 +890,8 @@ void StarTrekEngine::updateActorPositionWhileWalking(Actor *actor, int16 x, int1 * a destination position it's walking to. */ void StarTrekEngine::chooseActorDirectionForWalking(Actor *actor, int16 srcX, int16 srcY, int16 destX, int16 destY) { - actor->granularPosX = srcX << 16; - actor->granularPosY = srcY << 16; + actor->granularPosX = srcX; + actor->granularPosY = srcY; int16 distX = destX - srcX; int16 distY = destY - srcY; @@ -887,11 +914,11 @@ void StarTrekEngine::chooseActorDirectionForWalking(Actor *actor, int16 srcX, in if (distX != 0) { if (distX > 0) - actor->speedX = 1 << 16; + actor->speedX = 1.0; else - actor->speedX = -1 << 16; // 0xffff0000 + actor->speedX = -1.0; - actor->speedY = (distY << 16) / absDistX; + actor->speedY = Fixed32(distY) / absDistX; } } else { @@ -910,11 +937,11 @@ void StarTrekEngine::chooseActorDirectionForWalking(Actor *actor, int16 srcX, in if (distY != 0) { if (distY > 0) - actor->speedY = 1 << 16; + actor->speedY = 1.0; else - actor->speedY = -1 << 16; // 0xffff0000 + actor->speedY = -1.0; - actor->speedX = (distX << 16) / absDistY; + actor->speedX = Fixed32(distX) / absDistY; } } } @@ -939,12 +966,12 @@ bool StarTrekEngine::directPathExists(int16 srcX, int16 srcY, int16 destX, int16 if (distCounter == 0) return true; - speedY = (distY << 16) / absDistX; + speedY = Fixed32(distY) / absDistX; if (distX > 0) - speedX = 1 << 16; + speedX = 1.0; else - speedX = -1 << 16; + speedX = -1.0; } else { // absDistX <= absDistY distCounter = absDistY; @@ -952,25 +979,25 @@ bool StarTrekEngine::directPathExists(int16 srcX, int16 srcY, int16 destX, int16 if (distCounter == 0) return true; - speedX = (distX << 16) / absDistY; + speedX = Fixed32(distX) / absDistY; if (distY > 0) - speedY = 1 << 16; + speedY = 1.0; else - speedY = -1 << 16; + speedY = -1.0; } - Fixed32 fixedX = srcX << 16; - Fixed32 fixedY = srcY << 16; + Fixed32 fixedX = srcX; + Fixed32 fixedY = srcY; - if (isPositionSolid((fixedX + 0x8000) >> 16, (fixedY + 0x8000) >> 16)) + if (isPositionSolid((fixedX + 0.5).toInt(), (fixedY + 0.5).toInt())) return false; while (distCounter-- > 0) { fixedX += speedX; fixedY += speedY; - if (isPositionSolid((fixedX + 0x8000) >> 16, (fixedY + 0x8000) >> 16)) + if (isPositionSolid((fixedX + 0.5).toInt(), (fixedY + 0.5).toInt())) return false; } @@ -1119,7 +1146,7 @@ SharedPtr StarTrekEngine::loadAnimationFrame(const Common::String &filen bitmapToReturn = _gfx->loadBitmap(filename); } - if (scale != 256) { + if (scale != 1.0) { bitmapToReturn = scaleBitmap(bitmapToReturn, scale); } @@ -1454,7 +1481,7 @@ void StarTrekEngine::updateCrewmanGetupTimers() { } else { const char *dirs = "nsew"; - uint16 scale = getActorScaleAtPosition(actor->sprite.pos.y); + Fixed16 scale = getActorScaleAtPosition(actor->sprite.pos.y); d = dirs[dir]; int16 xOffset = 0, yOffset = 0; @@ -1466,8 +1493,8 @@ void StarTrekEngine::updateCrewmanGetupTimers() { xOffset = -35; yOffset = -12; } - actor->sprite.pos.x += (scale * xOffset) >> 8; - actor->sprite.pos.y += (scale * yOffset) >> 8; + actor->sprite.pos.x += scale.multToInt(xOffset); + actor->sprite.pos.y += scale.multToInt(yOffset); } anim += (char)d; @@ -1652,12 +1679,9 @@ void StarTrekEngine::initStarfieldSprite(Sprite *sprite, SharedPtr bitma sprite->drawMode = 1; } -/** - * A scale of 256 is the baseline. - */ SharedPtr StarTrekEngine::scaleBitmap(SharedPtr bitmap, Fixed16 scale) { - int scaledWidth = (bitmap->width * scale) >> 8; - int scaledHeight = (bitmap->height * scale) >> 8; + int scaledWidth = scale.multToInt(bitmap->width); + int scaledHeight = scale.multToInt(bitmap->height); int origWidth = bitmap->width; int origHeight = bitmap->height; @@ -1667,8 +1691,8 @@ SharedPtr StarTrekEngine::scaleBitmap(SharedPtr bitmap, Fixed16 scaledHeight = 1; SharedPtr scaledBitmap(new Bitmap(scaledWidth, scaledHeight)); - scaledBitmap->xoffset = (bitmap->xoffset * scale) >> 8; - scaledBitmap->yoffset = (bitmap->yoffset * scale) >> 8; + scaledBitmap->xoffset = scale.multToInt(bitmap->xoffset); + scaledBitmap->yoffset = scale.multToInt(bitmap->yoffset); // sub_344a5(scaledWidth, origWidth); @@ -1678,7 +1702,7 @@ SharedPtr StarTrekEngine::scaleBitmap(SharedPtr bitmap, Fixed16 byte *src = bitmap->pixels; byte *dest = scaledBitmap->pixels; - if (scale <= 256) { + if (scale <= 1.0) { int16 var2e = 0; uint16 var30 = scaledHeight << 1; uint16 var32 = (scaledHeight - origHeight) << 1; diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h index 3f5636f9db..1ec54f1ac3 100644 --- a/engines/startrek/startrek.h +++ b/engines/startrek/startrek.h @@ -222,7 +222,7 @@ public: void handleAwayMissionEvents(); void unloadRoom(); int loadActorAnimWithRoomScaling(int actorIndex, const Common::String &animName, int16 x, int16 y); - uint16 getActorScaleAtPosition(int16 y); + Fixed16 getActorScaleAtPosition(int16 y); void addAction(const Action &action); void addAction(byte type, byte b1, byte b2, byte b3); bool checkItemInteractionExists(int action, int activeItem, int passiveItem, int16 arg6); @@ -240,18 +240,30 @@ public: private: // Intro void playIntro(); + /** + * Initializes an object to spawn at one position and move toward another position. + * @param ticks The number of ticks it should take for the object to reach the destination + */ + void initIntroR3ObjectToMove(R3 *r3, int16 srcAngle, int16 srcDepth, int16 destAngle, int16 destDepth, int16 ticks); void loadSubtitleSprite(int index, Sprite *sprite); // Space, pseudo-3D (space.cpp) void initStarfieldPosition(); void initStarfield(int16 x, int16 y, int16 width, int16 height, int16 arg8); + void addR3(R3 *r3); + void delR3(R3 *r3); void clearStarfieldPixels(); void drawStarfield(); void updateStarfieldAndShips(bool arg0); Point3 constructPoint3ForStarfield(int16 x, int16 y, int16 z); - Point3 applyPointWeightings(Point3W *weight, const Point3 &point); - Point3 applyPointWeightings2(const Point3 &point, Point3W *weight); + Point3 matrixMult(const Matrix &weight, const Point3 &point); + Point3 matrixMult(const Point3 &point, const Matrix &weight); + + /** + * Creates something like an "identity" matrix? (Value 0x4000 along the diagonal) + */ + Matrix initMatrix(); // Transporter room void runTransportSequence(const Common::String &name); @@ -447,7 +459,7 @@ public: Common::String _screenName; // _screenName = _missionName + _roomIndex Common::String _mapFilename; // Similar to _screenName, but used for .map files? SharedPtr _mapFile; - int32 _playerActorScale; + Fixed32 _playerActorScale; Common::String _txtFilename; Common::String _loadedText; // TODO: might be OK to delete this @@ -519,6 +531,10 @@ public: int16 _starfieldXVar1, _starfieldYVar1; int16 _starfieldXVar2, _starfieldYVar2; Common::Rect _starfieldRect; + R3 _enterpriseR3; + R3 *_r3List[NUM_SPACE_OBJECTS]; + Matrix _starPositionMatrix; + Matrix _someMatrix; Graphics *_gfx; Sound *_sound; -- cgit v1.2.3