aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStrangerke2014-06-12 07:20:55 +0200
committerStrangerke2014-06-12 07:20:55 +0200
commit207f3c8be22b03b8f33e1f92a9010613747a5d03 (patch)
tree99925ee11fe8de2a773b2d32ec3122ef847b962d
parent45f8bd755cd6d741f6c342272e01ce1af6464ea7 (diff)
downloadscummvm-rg350-207f3c8be22b03b8f33e1f92a9010613747a5d03.tar.gz
scummvm-rg350-207f3c8be22b03b8f33e1f92a9010613747a5d03.tar.bz2
scummvm-rg350-207f3c8be22b03b8f33e1f92a9010613747a5d03.zip
CGE2: Implement FXP code. Still WIP, loadTab to be fixed
-rw-r--r--engines/cge2/cge2.h1
-rw-r--r--engines/cge2/cge2_main.cpp37
-rw-r--r--engines/cge2/fileio.cpp4
-rw-r--r--engines/cge2/fileio.h1
-rw-r--r--engines/cge2/hero.cpp39
-rw-r--r--engines/cge2/text.cpp4
-rw-r--r--engines/cge2/vga13h.cpp39
-rw-r--r--engines/cge2/vga13h.h86
8 files changed, 142 insertions, 69 deletions
diff --git a/engines/cge2/cge2.h b/engines/cge2/cge2.h
index a3d6f99a22..cb5e6205e8 100644
--- a/engines/cge2/cge2.h
+++ b/engines/cge2/cge2.h
@@ -43,6 +43,7 @@ class Fx;
class Sound;
class Text;
struct HeroTab;
+class FXP;
class V3D;
class V2D;
struct Dac;
diff --git a/engines/cge2/cge2_main.cpp b/engines/cge2/cge2_main.cpp
index 99b0f26c21..2809de16e2 100644
--- a/engines/cge2/cge2_main.cpp
+++ b/engines/cge2/cge2_main.cpp
@@ -702,34 +702,23 @@ void CGE2Engine::loadTab() {
for (int i = 0; i < kCaveMax; i++)
*(_eyeTab[i]) = *_eye;
- /*
- if (_resman->exist(kTabName)) {
+if (_resman->exist(kTabName)) {
EncryptedStream f(this, kTabName);
for (int i = 0; i < kCaveMax; i++) {
- for (int j = 0; j < 3; j++) {
- signed b = f.readSint16BE();
- unsigned a = f.readUint16BE();
- uint16 round = uint16((long(a) << 16) / 100);
-
- if (round > 0x7FFF)
- b++;
-
- switch (j) {
- case 0:
- _eyeTab[i]->_x = b;
- break;
- case 1:
- _eyeTab[i]->_y = b;
- break;
- case 2:
- _eyeTab[i]->_z = b;
- break;
- }
-
- }
+ int16 varI = f.readSint16LE();
+ int16 varF = f.readUint16LE();
+ _eyeTab[i]->_x = FXP(varI, varF);
+
+ varI = f.readSint16LE();
+ varF = f.readUint16LE();
+ _eyeTab[i]->_y = FXP(varI, varF);
+
+ varI = f.readSint16LE();
+ varF = f.readUint16LE();
+ _eyeTab[i]->_z = FXP(varI, varF);
}
}
- */
+
warning("STUB: CGE2Engine::loadTab()");
}
diff --git a/engines/cge2/fileio.cpp b/engines/cge2/fileio.cpp
index 4fec4a67ca..0ec1bce043 100644
--- a/engines/cge2/fileio.cpp
+++ b/engines/cge2/fileio.cpp
@@ -228,6 +228,10 @@ signed EncryptedStream::readSint16LE() {
return _readStream->readSint16LE();
}
+signed EncryptedStream::readUint16LE() {
+ return _readStream->readUint16LE();
+}
+
bool EncryptedStream::err() {
return (_error & _readStream->err());
}
diff --git a/engines/cge2/fileio.h b/engines/cge2/fileio.h
index 83a14560ad..6bf59424ef 100644
--- a/engines/cge2/fileio.h
+++ b/engines/cge2/fileio.h
@@ -125,6 +125,7 @@ public:
unsigned readUint16BE();
signed readSint16BE();
signed readSint16LE();
+ signed readUint16LE();
Common::String readLine();
int getLineCount() { return _lineCount; }
diff --git a/engines/cge2/hero.cpp b/engines/cge2/hero.cpp
index d6dab6d3f0..2671d0ea60 100644
--- a/engines/cge2/hero.cpp
+++ b/engines/cge2/hero.cpp
@@ -205,8 +205,9 @@ Sprite *Hero::expand() { // It's very similar to Sprite's expand, but doesn't bo
}
void Hero::setCurrent() {
- double m = _vm->_eye->_z / (_pos3D._z - _vm->_eye->_z);
- int h = -(V2D::trunc(m * _siz.y));
+ FXP m = _vm->_eye->_z / (_pos3D._z - _vm->_eye->_z);
+ FXP tmp = m * _siz.y;
+ int h = -(tmp.trunc());
int i = 0;
for (; i < kDimMax; i++) {
@@ -243,15 +244,15 @@ void Hero::tick() {
int Hero::distance(V3D pos) {
V3D di = _pos3D - pos;
- long x = V2D::round(di._x);
- long z = V2D::round(di._z);
- return (int)sqrt((long double)(x * x + z * z));
+ int x = di._x.round();
+ int z = di._z.round();
+ return ((int)sqrt((long double)x * x + z * z));
}
int Hero::distance(Sprite *spr) {
V3D pos = spr->_pos3D;
int mdx = (spr->_siz.x >> 1) + (_siz.x >> 1);
- int dx = V2D::round(_pos3D._x - spr->_pos3D._x);
+ int dx = (_pos3D._x - spr->_pos3D._x).round();
if (dx < 0) {
mdx = -mdx;
if (dx > mdx)
@@ -303,8 +304,8 @@ int Hero::len(V2D v) {
}
bool Hero::findWay(){
- V2D p0(_vm, V2D::round(_pos3D._x), V2D::round(_pos3D._z));
- V2D p1(_vm, V2D::round(_trace[_tracePtr]._x), V2D::round(_trace[_tracePtr]._z));
+ V2D p0(_vm, _pos3D._x.round(), _pos3D._z.round());
+ V2D p1(_vm, _trace[_tracePtr]._x.round(), _trace[_tracePtr]._z.round());
bool pvOk;
bool phOk;
V2D ph(_vm, p1.x, p0.y);
@@ -340,12 +341,12 @@ void Hero::walkTo(V3D pos) {
if (distance(pos) <= _maxDist)
return;
int stp = stepSize();
- pos._x = snap(V2D::round(_pos3D._x), V2D::round(pos._x), stp);
+ pos._x = snap(_pos3D._x.round(), pos._x.round(), stp);
pos._y = 0;
- pos._z = snap(V2D::round(_pos3D._z), V2D::round(pos._z), stp);
+ pos._z = snap(_pos3D._z.round(), pos._z.round(), stp);
- V2D p0(_vm, V2D::round(_pos3D._x), V2D::round(_pos3D._z));
- V2D p1(_vm, V2D::round(pos._x), V2D::round(pos._z));
+ V2D p0(_vm, _pos3D._x.round(), _pos3D._z.round());
+ V2D p1(_vm, pos._x.round(), pos._z.round());
resetFun();
int cnt = mapCross(p0, p1);
if ((cnt & 1) == 0) { // even == way exists
@@ -385,15 +386,15 @@ void Hero::walkTo(Sprite *spr) {
}
V3D Hero::screenToGround(V2D pos) {
- double z = _vm->_eye->_z + (_vm->_eye->_y * _vm->_eye->_z) / (double(pos.y) - _vm->_eye->_y);
- double x = _vm->_eye->_x - ((double(pos.x) - _vm->_eye->_x) * (z - _vm->_eye->_z)) / _vm->_eye->_z;
- return V3D(V2D::round(x), 0, V2D::round(z));
+ FXP z = _vm->_eye->_z + (_vm->_eye->_y * _vm->_eye->_z) / (FXP(pos.y) - _vm->_eye->_y);
+ FXP x = _vm->_eye->_x - ((FXP(pos.x) - _vm->_eye->_x) * (z - _vm->_eye->_z)) / _vm->_eye->_z;
+ return V3D(x.round(), 0, z.round());
}
int Hero::cross(const V2D &a, const V2D &b) {
- int x = V2D::trunc(_pos3D._x);
- int z = V2D::trunc(_pos3D._z);
- int r = ((_siz.x / 3) * V2D::trunc(_vm->_eye->_z)) / (V2D::trunc(_vm->_eye->_z) - z);
+ int x = _pos3D._x.trunc();
+ int z = _pos3D._z.trunc();
+ int r = ((_siz.x / 3) * _vm->_eye->_z.trunc()) / (_vm->_eye->_z.trunc()- z);
return _vm->cross(a, b, V2D(_vm, x - r, z), V2D(_vm, x + r, z)) << 1;
}
@@ -433,7 +434,7 @@ int Hero::mapCross(const V2D &a, const V2D &b) {
}
int Hero::mapCross(const V3D &a, const V3D &b) {
- return mapCross(V2D(_vm, V2D::round(a._x), V2D::round(a._z)), V2D(_vm, V2D::round(b._x), V2D::round(b._z)));
+ return mapCross(V2D(_vm, a._x.round(), a._z.round()), V2D(_vm, b._x.round(), b._z.round()));
}
int CGE2Engine::mapCross(const V2D &a, const V2D &b) {
diff --git a/engines/cge2/text.cpp b/engines/cge2/text.cpp
index 83088eab25..cf4dda4703 100644
--- a/engines/cge2/text.cpp
+++ b/engines/cge2/text.cpp
@@ -145,7 +145,7 @@ void Text::say(const char *text, Sprite *spr) {
if (!east)
d.x = -d.x;
if (_vm->isHero(spr))
- d = d.scale(V2D::trunc(spr->_pos3D._z));
+ d = d.scale(spr->_pos3D._z.trunc());
V2D pos = spr->_pos2D + d;
uint16 sw = (speaker->_siz.x >> 1);
if (!east)
@@ -168,7 +168,7 @@ void Text::say(const char *text, Sprite *spr) {
_vm->_talk->setName(getText(kSayName));
_vm->_talk->gotoxyz(pos.x, pos.y + speaker->_siz.y - 1, 0);
- speaker->gotoxyz(pos.x, V2D::trunc(_vm->_talk->_pos3D._y) - speaker->_siz.y + 1, 0);
+ speaker->gotoxyz(pos.x, _vm->_talk->_pos3D._y.trunc() - speaker->_siz.y + 1, 0);
speaker->_flags._slav = true;
speaker->_flags._kill = true;
speaker->setName(getText(kSayName));
diff --git a/engines/cge2/vga13h.cpp b/engines/cge2/vga13h.cpp
index 61b367b7a5..e59e82579e 100644
--- a/engines/cge2/vga13h.cpp
+++ b/engines/cge2/vga13h.cpp
@@ -531,9 +531,9 @@ void Sprite::gotoxyz(V2D pos) {
byte trim = 0;
if (_ref / 10 == 14) { // HERO
- int z = V2D::trunc(_pos3D._z);
- ctr = (ctr * V2D::trunc(_vm->_eye->_z) / (V2D::trunc(_vm->_eye->_z) - z));
- rem = (rem * V2D::trunc(_vm->_eye->_z) / (V2D::trunc(_vm->_eye->_z) - z));
+ int z = _pos3D._z.trunc();
+ ctr = (ctr * _vm->_eye->_z.trunc()) / (_vm->_eye->_z.trunc() - z);
+ rem = (rem * _vm->_eye->_z.trunc()) / (_vm->_eye->_z.trunc() - z);
ctr = (ctr * 3) / 4;
rem = (rem * 3) / 4;
}
@@ -561,10 +561,15 @@ void Sprite::gotoxyz(V2D pos) {
_flags._trim = (trim != 0);
if (!_follow) {
- double m = _vm->_eye->_z / (_pos3D._z - _vm->_eye->_z);
- _pos3D._x = V2D::round(_vm->_eye->_x + (_vm->_eye->_x - _pos2D.x) / m);
- if (!_constY)
- _pos3D._y = V2D::round(_vm->_eye->_y + (_vm->_eye->_y - _pos2D.y) / m);
+ // CHECKME: Original was using Pos2d.Eye, which shouldn't make a difference (static var)
+ FXP m = _vm->_eye->_z / (_pos3D._z - _vm->_eye->_z);
+ _pos3D._x = (_vm->_eye->_x + (_vm->_eye->_x - _pos2D.x) / m);
+ _pos3D._x.round();
+
+ if (!_constY) {
+ _pos3D._y = _vm->_eye->_y + (_vm->_eye->_y - _pos2D.y) / m;
+ _pos3D._y.round();
+ }
}
if (_next && _next->_flags._slav)
@@ -685,9 +690,23 @@ void Sprite::sync(Common::Serializer &s) {
s.syncAsUint16LE(flags);
}
- s.syncAsUint16LE(_pos3D._x);
- s.syncAsUint16LE(_pos3D._y);
- s.syncAsByte(_pos3D._z);
+ int pos = 0;
+ if (s.isLoading()) {
+ s.syncAsSint16LE(pos);
+ _pos3D._x = FXP(pos, 0);
+ s.syncAsSint16LE(pos);
+ _pos3D._y = pos;
+ s.syncAsSint16LE(pos);
+ _pos3D._z = pos;
+ } else {
+ pos = _pos3D._x.trunc();
+ s.syncAsUint16LE(pos);
+ pos = _pos3D._y.trunc();
+ s.syncAsUint16LE(pos);
+ pos = _pos3D._z.trunc();
+ s.syncAsByte(pos);
+ }
+
s.syncAsUint16LE(_time);
s.syncAsSint16LE(_seqPtr);
s.syncAsUint16LE(_shpCnt);
diff --git a/engines/cge2/vga13h.h b/engines/cge2/vga13h.h
index 09eb61accf..73667bca91 100644
--- a/engines/cge2/vga13h.h
+++ b/engines/cge2/vga13h.h
@@ -51,19 +51,74 @@ namespace CGE2 {
#define kPalCount 256
#define kPalSize (kPalCount * 3)
+// From FXP.H
+class FXP // fixed point
+{
+ uint16 f;
+ int16 i;
+ long& Joined (void) const { return *(long *)&f; }
+public:
+ FXP (void) { }
+ FXP (int i0, int f0 = 0) : i(i0), f((int) ((((long) f0) << 16)/100)) { }
+ FXP& operator = (const int& x) { i = x; f = 0; return *this; }
+ FXP operator + (const FXP& x) const { FXP y; y.Joined() = Joined()+x.Joined(); return y; }
+ FXP operator - (const FXP& x) const { FXP y; y.Joined() = Joined()-x.Joined(); return y; }
+ FXP operator * (const FXP& x) const {
+ FXP y; long t;
+ y.i = i * x.i;
+ t = ((long) f * x.f) >> 16;
+ t += ((long) i * x.f) + ((long) f * x.i);
+ y.f = t & 0xFFFF;
+ y.i += t >> 16;
+ return y;
+ }
+ FXP operator / (const FXP& x) const {
+ FXP y; bool sign = false;
+ long j = Joined(), jx = x.Joined();
+ if (j < 0) {
+ j = -j;
+ sign ^= 1;
+ }
+ if (jx < 0) {
+ jx = -jx;
+ sign ^= 1;
+ }
+ y.i = signed(j / jx);
+ long r = j - jx * y.i;
+ //-- binary division
+ y.f = unsigned((r << 4) / (jx >> 12));
+ //------------------
+ if (sign)
+ y.Joined() = -y.Joined();
+
+ return y;
+ }
+ //int& operator = (int& a, const FXP& b) { return a = b.i; }
+ friend int& operator += (int& a, const FXP& b) { return a += b.i; }
+ friend int& operator -= (int& a, const FXP& b) { return a -= b.i; }
+ friend FXP& operator += (FXP& a, const int& b) { a.i += b; return a; }
+ friend FXP& operator -= (FXP& a, const int& b) { a.i -= b; return a; }
+ friend bool operator == (const FXP &a, const FXP &b) { return (a.i == b.i) && (a.f == b.f); }
+ friend bool operator != (const FXP &a, const FXP &b) { return (a.i != b.i) || (a.f != b.f); }
+ friend bool operator < (const FXP &a, const FXP &b) { return (a.i < b.i) || ((a.i == b.i) && (a.f < b.f)); }
+ friend bool operator > (const FXP &a, const FXP &b) { return (a.i > b.i) || ((a.i == b.i) && (a.f > b.f)); }
+ int trunc(void) const { return i; }
+ int round(void) const { return i + (f > 0x7FFF); }
+};
+
// From CGETYPE.H:
class V3D {
public:
- double _x, _y, _z;
+ FXP _x, _y, _z;
V3D() { }
- V3D(double x, double y, double z = 0) : _x(x), _y(y), _z(z) { }
+ V3D(FXP x, FXP y, FXP z = 0) : _x(x), _y(y), _z(z) { }
V3D(const V3D &p) : _x(p._x), _y(p._y), _z(p._z) { }
V3D operator+(const V3D &p) const { return V3D(_x + p._x, _y + p._y, _z + p._z); }
V3D operator-(const V3D &p) const { return V3D(_x - p._x, _y - p._y, _z - p._z); }
V3D operator*(long n) const { return V3D(_x * n, _y * n, _z * n); }
V3D operator/ (long n) const { return V3D(_x / n, _y / n, _z / n); }
- bool operator==(V3D &p) const { return _x == p._x && _y == p._y && _z == p._z; }
- bool operator!=(V3D &p) const { return _x != p._x || _y != p._y || _z != p._z; }
+ bool operator==(const V3D &p) const { return _x == p._x && _y == p._y && _z == p._z; }
+ bool operator!=(const V3D &p) const { return _x != p._x || _y != p._y || _z != p._z; }
V3D& operator+=(const V3D &x) { return *this = *this + x; }
V3D& operator-=(const V3D &x) { return *this = *this - x; }
};
@@ -72,11 +127,11 @@ class V2D : public Common::Point {
CGE2Engine *_vm;
public:
V2D& operator=(const V3D &p3) {
- if (p3._z == 200)
- warning("");
- double m = _vm->_eye->_z / (p3._z - _vm->_eye->_z);
- x = round(_vm->_eye->_x + (_vm->_eye->_x - p3._x) * m);
- y = round(_vm->_eye->_y + (_vm->_eye->_y - p3._y) * m);
+ FXP m = _vm->_eye->_z / (p3._z - _vm->_eye->_z);
+ FXP posx = _vm->_eye->_x + (_vm->_eye->_x - p3._x) * m;
+ x = posx.round();
+ FXP posy = _vm->_eye->_y + (_vm->_eye->_y - p3._y) * m;
+ y = posy.round();
return *this;
}
V2D(CGE2Engine *vm) : _vm(vm) { }
@@ -88,14 +143,17 @@ public:
bool operator>=(const V2D &p) const { return (x >= p.x) && (y >= p.y); }
V2D operator+(const V2D &p) const { return V2D(_vm, x + p.x, y + p.y); }
V2D operator-(const V2D &p) const { return V2D(_vm, x - p.x, y - p.y); }
+ bool operator==(const V3D &p) const { V3D tmp(x, y); return tmp._x == p._x && tmp._y == p._y && tmp._z == p._z; }
+ bool operator!=(const V3D &p) const { V3D tmp(x, y); return tmp._x != p._x || tmp._y != p._y || tmp._z == p._z; }
uint16 area() { return x * y; }
bool limited(const V2D &p) {
- return (uint16(x) < uint16(p.x)) && (uint16(y) < uint16(p.y));
+ return ((x < p.x) && (y < p.y));
}
- V2D scale(int z) {
- double m = _vm->_eye->_z / (_vm->_eye->_z - z);
- warning("scale: %f %f %f, x, y, m");
- return V2D(_vm, trunc(m * x), trunc(m * y));
+ V2D scale (int z) {
+ FXP m = _vm->_eye->_z / (_vm->_eye->_z - z);
+ FXP posx = m * x;
+ FXP posy = m * y;
+ return V2D(_vm, posx.trunc(), posy.trunc());
}
static double trunc(double d) { return (d > 0) ? floor(d) : ceil(d); }
static double round(double number) { return number < 0.0 ? ceil(number) : floor(number); }