CGE2: Implement FXP code. Still WIP, loadTab to be fixed

This commit is contained in:
Strangerke 2014-06-12 07:20:55 +02:00
parent 45f8bd755c
commit 207f3c8be2
8 changed files with 142 additions and 69 deletions

View File

@ -43,6 +43,7 @@ class Fx;
class Sound;
class Text;
struct HeroTab;
class FXP;
class V3D;
class V2D;
struct Dac;

View File

@ -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()");
}

View File

@ -228,6 +228,10 @@ signed EncryptedStream::readSint16LE() {
return _readStream->readSint16LE();
}
signed EncryptedStream::readUint16LE() {
return _readStream->readUint16LE();
}
bool EncryptedStream::err() {
return (_error & _readStream->err());
}

View File

@ -125,6 +125,7 @@ public:
unsigned readUint16BE();
signed readSint16BE();
signed readSint16LE();
signed readUint16LE();
Common::String readLine();
int getLineCount() { return _lineCount; }

View File

@ -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) {

View File

@ -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));

View File

@ -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);

View File

@ -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); }