From 207f3c8be22b03b8f33e1f92a9010613747a5d03 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Thu, 12 Jun 2014 07:20:55 +0200 Subject: CGE2: Implement FXP code. Still WIP, loadTab to be fixed --- engines/cge2/cge2.h | 1 + engines/cge2/cge2_main.cpp | 37 +++++++------------- engines/cge2/fileio.cpp | 4 +++ engines/cge2/fileio.h | 1 + engines/cge2/hero.cpp | 39 +++++++++++---------- engines/cge2/text.cpp | 4 +-- engines/cge2/vga13h.cpp | 39 +++++++++++++++------ engines/cge2/vga13h.h | 86 ++++++++++++++++++++++++++++++++++++++-------- 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); } -- cgit v1.2.3