Permalink
Browse files

STARTREK: Implement fixed-point decimal class

  • Loading branch information...
Drenn1 authored and sev- committed Jul 19, 2018
1 parent a024a3f commit ac9cd1f00a28b09dd0202c90a2fe023bc8cba525
@@ -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<Room> StarTrekEngine::getRoom() {
@@ -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
@@ -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<typename T, uint totalBits, uint decimalBits>
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<typename T2, uint otherTB, uint otherDB>
TFixedInt<T, totalBits, decimalBits>(const TFixedInt<T2, otherTB, otherDB> &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<typename T, uint totalBits, uint decimalBits>
int32 operator*(const int16 lhs, const TFixedInt<T, totalBits, decimalBits> &rhs) {
return rhs * lhs;
}


// Fixed-point (2.14) number (between -1 and 1)
typedef TFixedInt<int16, 16, 14> Fixed14;

// Fixed-point (8.8) number
typedef TFixedInt<int16, 16, 8> Fixed16;

// Fixed-point (16.16) number
typedef TFixedInt<int32, 32, 16> Fixed32;

}

#endif
@@ -24,6 +24,7 @@
#define STARTREK_OBJECT_H

#include "startrek/common.h"
#include "startrek/fixedint.h"
#include "startrek/items.h"
#include "startrek/sprite.h"

@@ -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;
@@ -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 @@ class Room {
// 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.
@@ -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);
Oops, something went wrong.

0 comments on commit ac9cd1f

Please sign in to comment.