mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-05 09:49:14 +00:00
STARTREK: Half-done implementation of drawR3Shape
Handles drawing, scaling, probably rotating objects in space.
This commit is contained in:
parent
565bf0e967
commit
eff87179da
@ -56,7 +56,7 @@ public:
|
||||
* Constructor from other fixed-point formats.
|
||||
*/
|
||||
template<typename T2, uint otherTB, uint otherDB>
|
||||
TFixedInt<T, totalBits, decimalBits>(const TFixedInt<T2, otherTB, otherDB> &fi) {
|
||||
explicit TFixedInt<T, totalBits, decimalBits>(const TFixedInt<T2, otherTB, otherDB> &fi) {
|
||||
int diff = otherDB - decimalBits;
|
||||
if (otherDB >= decimalBits)
|
||||
val = fi.raw() >> diff;
|
||||
@ -76,12 +76,16 @@ public:
|
||||
return ((double)val) / (1 << decimalBits);
|
||||
}
|
||||
|
||||
TFixedInt operator-() const {
|
||||
return fromRaw(-val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplication with an int, with the result being an int. Use this if the result
|
||||
* might exceed the capacity of this type.
|
||||
*/
|
||||
int16 multToInt(int32 i) {
|
||||
return (val * i) >> decimalBits;
|
||||
return ((int32)(val * i)) >> decimalBits;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,6 +94,12 @@ public:
|
||||
TFixedInt operator*(int32 i) const {
|
||||
return fromRaw(val * i);
|
||||
}
|
||||
/**
|
||||
* Multiplication with a FixedInt, with the result being the same type.
|
||||
*/
|
||||
TFixedInt operator*(const TFixedInt &f) const {
|
||||
return fromRaw(((int32)(val * f.val)) >> decimalBits);
|
||||
}
|
||||
/**
|
||||
* Division with an int, with the result being the same type.
|
||||
*/
|
||||
@ -173,6 +183,8 @@ typedef TFixedInt<int16, 16, 8> Fixed8;
|
||||
// Fixed-point (16.16) number
|
||||
typedef TFixedInt<int32, 32, 16> Fixed16;
|
||||
|
||||
typedef Fixed8 Angle;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -105,6 +105,10 @@ void Graphics::fillBackgroundRect(const Common::Rect &rect, byte color) {
|
||||
}
|
||||
}
|
||||
|
||||
byte *Graphics::getBackgroundPixels() {
|
||||
return _backgroundImage->pixels;
|
||||
}
|
||||
|
||||
void Graphics::clearScreenAndPriBuffer() {
|
||||
Common::fill(_priData, _priData + sizeof(_priData), 0);
|
||||
|
||||
@ -131,6 +135,17 @@ void Graphics::loadPalette(const Common::String &paletteName) {
|
||||
lutStream->read(_lutData, 256);
|
||||
}
|
||||
|
||||
void Graphics::copyRectBetweenBitmaps(Bitmap *destBitmap, int destX, int destY, Bitmap *srcBitmap, int srcX, int srcY, int width, int height) {
|
||||
byte *src = srcBitmap->pixels + srcX + srcY * srcBitmap->width;
|
||||
byte *dest = destBitmap->pixels + destX + destY * destBitmap->width;
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
memcpy(dest, src, width);
|
||||
src += srcBitmap->width;
|
||||
dest += destBitmap->width;
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::fadeinScreen() {
|
||||
while (_paletteFadeLevel <= 100) {
|
||||
TrekEvent event;
|
||||
|
@ -58,10 +58,13 @@ public:
|
||||
* @param drawRect The clipped rectangle to draw at (must be within the drawable space)
|
||||
*/
|
||||
void drawBitmapToBackground(const Common::Rect &origRect, const Common::Rect &drawRect, SharedPtr<Bitmap> bitmap);
|
||||
|
||||
void fillBackgroundRect(const Common::Rect &rect, byte color);
|
||||
byte *getBackgroundPixels();
|
||||
|
||||
void clearScreenAndPriBuffer();
|
||||
void loadPalette(const String &paletteFile);
|
||||
void copyRectBetweenBitmaps(Bitmap *destBitmap, int destX, int destY, Bitmap *srcBitmap, int srcX, int srcY, int width, int height);
|
||||
void fadeinScreen();
|
||||
void fadeoutScreen();
|
||||
void setPaletteFadeLevel(byte *palData, int fadeLevel);
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
namespace StarTrek {
|
||||
|
||||
Fixed14 StarTrekEngine::sin(Fixed8 angle) {
|
||||
Fixed14 StarTrekEngine::sin(Angle angle) {
|
||||
int16 i = angle.raw();
|
||||
if (angle < 0) {
|
||||
i %= 0x400;
|
||||
@ -46,14 +46,14 @@ Fixed14 StarTrekEngine::sin(Fixed8 angle) {
|
||||
f = -_sineTable.getTable()[i & 0xff];
|
||||
else if (i < 0x400)
|
||||
f = -_sineTable.getTable()[256 - (i & 0xff)];
|
||||
return Fixed16(f);
|
||||
return Fixed14(f);
|
||||
}
|
||||
|
||||
Fixed14 StarTrekEngine::cos(Fixed8 angle) {
|
||||
Fixed14 StarTrekEngine::cos(Angle angle) {
|
||||
return sin(angle + 1.0);
|
||||
}
|
||||
|
||||
Fixed8 StarTrekEngine::atan2(int32 deltaX, int32 deltaY) {
|
||||
Angle StarTrekEngine::atan2(int32 deltaX, int32 deltaY) {
|
||||
const int16 atanTable[] = {
|
||||
0x0000, 0x0064, 0x00c9, 0x012d, 0x0192, 0x01f6, 0x025b, 0x02c0,
|
||||
0x0324, 0x0389, 0x03ee, 0x0453, 0x04b8, 0x051d, 0x0582, 0x05e8,
|
||||
@ -85,9 +85,9 @@ Fixed8 StarTrekEngine::atan2(int32 deltaX, int32 deltaY) {
|
||||
|
||||
Fixed14 ratio;
|
||||
if (deltaY > deltaX)
|
||||
ratio = Fixed14::fromRaw(((deltaX & 0xffff0000) >> 2) / (deltaY >> 16));
|
||||
ratio = Fixed14::fromRaw(((deltaX & 0xffff0000) >> 2) / deltaY);
|
||||
else
|
||||
ratio = Fixed14::fromRaw(((deltaY & 0xffff0000) >> 2) / (deltaX >> 16));
|
||||
ratio = Fixed14::fromRaw(((deltaY & 0xffff0000) >> 2) / deltaX);
|
||||
|
||||
int16 endIndex = 128;
|
||||
int16 index = 0;
|
||||
@ -123,7 +123,7 @@ Fixed8 StarTrekEngine::atan2(int32 deltaX, int32 deltaY) {
|
||||
angle = -256 + angle;
|
||||
}
|
||||
|
||||
return Fixed8::fromRaw(angle);
|
||||
return Angle::fromRaw(angle);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ void StarTrekEngine::initStarfieldPosition() {
|
||||
}
|
||||
|
||||
void StarTrekEngine::initStarfield(int16 x, int16 y, int16 width, int16 height, int16 arg8) {
|
||||
// TODO: finish
|
||||
_starfieldXVar1 = (x + width) / 2;
|
||||
_starfieldYVar1 = (y + height) / 2;
|
||||
_starfieldXVar2 = (width - x + 1) / 2;
|
||||
@ -43,6 +44,7 @@ void StarTrekEngine::initStarfield(int16 x, int16 y, int16 width, int16 height,
|
||||
|
||||
memset(_starList, 0, sizeof(_starList));
|
||||
_starfieldPointDivisor = 150;
|
||||
_flt_50898 = 50.0;
|
||||
}
|
||||
|
||||
void StarTrekEngine::addR3(R3 *r3) {
|
||||
@ -73,9 +75,6 @@ void StarTrekEngine::clearStarfieldPixels() {
|
||||
}
|
||||
|
||||
void StarTrekEngine::drawStarfield() {
|
||||
// TODO: make these class variables
|
||||
float flt_50898 = 50.0; // ?
|
||||
|
||||
int16 var28 = ((_starfieldXVar2 * 3) >> 1);
|
||||
int16 xvar = var28 / 2;
|
||||
int16 var2a = ((_starfieldYVar2 * 3) >> 1);
|
||||
@ -101,11 +100,11 @@ void StarTrekEngine::drawStarfield() {
|
||||
Point3 p = star->pos - _starfieldPosition;
|
||||
Point3 point2 = matrixMult(p, _starPositionMatrix);
|
||||
|
||||
if (point2.z > flt_50898 && point2.z < 0x3fff
|
||||
if (point2.z > _flt_50898 && point2.z < 0x3fff
|
||||
&& abs(point2.x) < point2.z && abs(point2.y) < point2.z) {
|
||||
|
||||
int16 x = _starfieldXVar1 + (point2.x * _starfieldPointDivisor / point2.z);
|
||||
int16 y = _starfieldYVar1 - (point2.y * _starfieldPointDivisor / point2.z);
|
||||
int16 x = _starfieldXVar1 + scaleSpacePosition(point2.x, point2.z);
|
||||
int16 y = _starfieldYVar1 - scaleSpacePosition(point2.y, point2.z);
|
||||
|
||||
int fileOffset = file->pos();
|
||||
file->readUint32();
|
||||
@ -131,13 +130,371 @@ void StarTrekEngine::drawStarfield() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare 2 r3 objects for the purpose of sorting them by layer before drawing.
|
||||
* FIXME: Original returned an int, not a bool. This may affect the stability of the sort...
|
||||
*/
|
||||
bool compareR3Objects(R3 *obj1, R3 *obj2) {
|
||||
int32 diff = obj1->field54 - obj2->field54;
|
||||
if (diff < 0)
|
||||
return true;
|
||||
else if (diff == 0)
|
||||
return false; // original would have a distinct value for this
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void StarTrekEngine::updateStarfieldAndShips(bool arg0) {
|
||||
bool enterpriseDestroyed = false;
|
||||
|
||||
_starfieldSprite.bitmapChanged = true;
|
||||
_starPositionMatrix = _someMatrix.invert();
|
||||
clearStarfieldPixels();
|
||||
drawStarfield();
|
||||
|
||||
// TODO
|
||||
int numObjects = 0;
|
||||
for (int i = 0; i < NUM_SPACE_OBJECTS; i++) {
|
||||
R3 *r3 = _r3List[i];
|
||||
if (r3 == nullptr)
|
||||
continue;
|
||||
r3->field34 = 0;
|
||||
|
||||
switch (r3->field1e) { // TODO
|
||||
case 1:
|
||||
r3 = sub_19f24(r3);
|
||||
break;
|
||||
case 2: // TODO (specifically for the enterprise?)
|
||||
break;
|
||||
case 3:
|
||||
r3 = sub_19f24(r3);
|
||||
break;
|
||||
}
|
||||
|
||||
if (r3 != nullptr)
|
||||
_orderedR3List[numObjects++] = r3;
|
||||
}
|
||||
|
||||
if (numObjects != 0) {
|
||||
Common::sort(_orderedR3List, _orderedR3List + numObjects, &compareR3Objects);
|
||||
|
||||
for (int i = 0; i < numObjects; i++) {
|
||||
R3 *r3 = _orderedR3List[i];
|
||||
r3->field34 = 1;
|
||||
|
||||
switch (r3->field1e) { // TODO
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
if (r3->field20 == 1) {
|
||||
// TODO
|
||||
} else
|
||||
drawR3Shape(r3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enterpriseDestroyed) {
|
||||
showTextbox("", "GENE\\SPACE000#The Enterprise has been destroyed!", 20, 20, TEXTCOLOR_YELLOW, 0);
|
||||
showGameOverMenu();
|
||||
// FIXME: original game manipulates stack to jump somewhere...
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: static on enterprise viewscreen?
|
||||
}
|
||||
|
||||
R3 *StarTrekEngine::sub_19f24(R3 *r3) {
|
||||
r3->matrix2 = r3->matrix;
|
||||
r3->field36 = r3->pos;
|
||||
r3->field36 -= _starfieldPosition;
|
||||
r3->field54 = r3->field36.getDiagonal();
|
||||
Point3 point = matrixMult(r3->field36, _starPositionMatrix);
|
||||
r3->field36 = point;
|
||||
|
||||
if (sub_1c022(r3)) {
|
||||
if (r3->field1e >= 1 && r3->field1e <= 3)
|
||||
r3->matrix2 *= _starPositionMatrix;
|
||||
r3->field58 = _starfieldXVar1 + scaleSpacePosition(r3->field36.x, r3->field36.z);
|
||||
r3->field5a = _starfieldYVar1 - scaleSpacePosition(r3->field36.y, r3->field36.z);
|
||||
return r3;
|
||||
} else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void StarTrekEngine::drawR3Shape(R3 *r3) {
|
||||
if (r3->field1e != 3) // TODO: remove this
|
||||
return;
|
||||
|
||||
if (r3->funcPtr1 != nullptr) {
|
||||
// TODO: call it
|
||||
}
|
||||
|
||||
if (r3->shpFile != nullptr) {
|
||||
r3->shpFile->seek(r3->bitmapOffset, SEEK_SET);
|
||||
SharedPtr<Bitmap> bitmap(new Bitmap(r3->shpFile));
|
||||
double dbl68 = ((double)r3->field24 * _starfieldPointDivisor) / r3->field36.z;
|
||||
double dbl70 = 1.0 / dbl68;
|
||||
|
||||
double dbl30;
|
||||
double dbl28;
|
||||
double dbl20;
|
||||
double dbl18;
|
||||
double dbl60;
|
||||
double dbl58;
|
||||
double dbl50;
|
||||
double dbl48;
|
||||
|
||||
switch (r3->field1e) {
|
||||
case 1: // TODO
|
||||
break;
|
||||
case 3:
|
||||
dbl30 = dbl68;
|
||||
dbl28 = 0.0;
|
||||
dbl20 = 0.0;
|
||||
dbl18 = dbl68;
|
||||
dbl60 = dbl70;
|
||||
dbl58 = 0.0;
|
||||
dbl50 = 0.0;
|
||||
dbl48 = dbl70;
|
||||
break;
|
||||
case 4: // TODO
|
||||
break;
|
||||
default: // TODO
|
||||
break;
|
||||
}
|
||||
|
||||
r3->field80 = dbl60;
|
||||
r3->field88 = dbl58;
|
||||
r3->field90 = dbl50;
|
||||
r3->field98 = dbl48;
|
||||
|
||||
// dbl30, (bitmap->xoffset + 2), r3->field58,
|
||||
double tmp = r3->field58 - (double)(bitmap->xoffset + 2) * dbl30;
|
||||
// dbl20, (bitmap->yoffset + 2), tmp
|
||||
double dbl10 = tmp - (double)(bitmap->yoffset + 2) * dbl20;
|
||||
|
||||
// dbl28, (bitmap->xoffset + 2), r3->field5a
|
||||
tmp = r3->field5a - (double)(bitmap->xoffset + 2) * dbl28;
|
||||
// dbl18, (bitmap->yoffset + 2), tmp
|
||||
double dbl8 = tmp - (double)(bitmap->yoffset + 2) * dbl18;
|
||||
|
||||
// dbl60, r3->field58, bitmap->xoffset + 2
|
||||
tmp = (bitmap->xoffset + 2) - dbl60 * r3->field58;
|
||||
double dbl40 = tmp - dbl50 * r3->field5a;
|
||||
|
||||
tmp = (bitmap->yoffset + 2) - dbl58 * r3->field58;
|
||||
double dbl38 = tmp - dbl48 * r3->field5a;
|
||||
|
||||
double dbl3e4 = bitmap->width + 2;
|
||||
double dbl3ec = bitmap->height + 2;
|
||||
|
||||
double thing[8];
|
||||
tmp = 1.0 * dbl30;
|
||||
thing[0] = 1.0 * dbl20 + tmp + dbl10;
|
||||
|
||||
tmp = 1.0 * dbl28;
|
||||
thing[1] = 1.0 * dbl18 + tmp + dbl8;
|
||||
|
||||
tmp = 1.0 * dbl30;
|
||||
thing[2] = dbl3ec * dbl20 + tmp + dbl10;
|
||||
|
||||
tmp = 1.0 * dbl28;
|
||||
thing[3] = dbl3ec * dbl18 + tmp + dbl8;
|
||||
|
||||
thing[4] = dbl3ec * dbl20 + dbl3e4 * dbl30 + dbl10;
|
||||
thing[5] = dbl3ec * dbl18 + dbl3e4 * dbl28 + dbl8;
|
||||
|
||||
thing[6] = 1.0 * dbl20 + dbl3e4 * dbl30 + dbl10;
|
||||
thing[7] = 1.0 * dbl18 + dbl3e4 * dbl28 + dbl8;
|
||||
|
||||
|
||||
int16 rightBounds[SCREEN_HEIGHT];
|
||||
int16 leftBounds[SCREEN_HEIGHT];
|
||||
|
||||
for (int y = _starfieldRect.top; y < _starfieldRect.bottom; y++) {
|
||||
leftBounds[y] = _starfieldRect.right;
|
||||
rightBounds[y] = _starfieldRect.left - 1;
|
||||
}
|
||||
|
||||
int16 shpImageTop = _starfieldRect.bottom - 1;
|
||||
int16 shpImageBottom = _starfieldRect.top;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int16 index1 = i;
|
||||
int16 index2 = (i + 1) & 3;
|
||||
|
||||
if (thing[index1 + 1] > thing[index2 + 1]) {
|
||||
index1 = index2;
|
||||
index2 = i;
|
||||
}
|
||||
|
||||
int16 top = ceil(thing[index1 + 1]);
|
||||
int16 bottom = floor(thing[index2 + 1]);
|
||||
|
||||
if (top > bottom)
|
||||
continue;
|
||||
if (top > _starfieldRect.bottom - 1) // FIXME
|
||||
continue;
|
||||
if (bottom < _starfieldRect.top)
|
||||
continue;
|
||||
if (top < _starfieldRect.top)
|
||||
top = _starfieldRect.top;
|
||||
if (bottom > _starfieldRect.bottom - 1)
|
||||
bottom = _starfieldRect.bottom - 1;
|
||||
|
||||
if (top < shpImageTop)
|
||||
shpImageTop = top;
|
||||
if (bottom > shpImageBottom)
|
||||
shpImageBottom = bottom;
|
||||
|
||||
double dbl3f4;
|
||||
if (thing[index2 + 1] == thing[index1 + 1])
|
||||
dbl3f4 = 0.0;
|
||||
else
|
||||
dbl3f4 = (thing[index2] - thing[index1]) / (thing[index2 + 1] - thing[index1 + 1]);
|
||||
|
||||
int32 var3ec = (int32)(0x10000 * dbl3f4);
|
||||
int32 var3e8 = (int32)(((top - thing[index1 + 1]) * dbl3f4 + thing[index1]) * 0x10000);
|
||||
|
||||
for (int y = top; y <= bottom; y++) {
|
||||
int16 var3f6 = var3e8 >> 16;
|
||||
int16 var3f8 = (var3e8 + 0xffff) >> 16;
|
||||
|
||||
if (var3f8 < _starfieldRect.left)
|
||||
var3f8 = _starfieldRect.left;
|
||||
if (var3f8 < leftBounds[y])
|
||||
leftBounds[y] = var3f8;
|
||||
|
||||
if (var3f6 > _starfieldRect.right - 1)
|
||||
var3f6 = _starfieldRect.right - 1;
|
||||
if (var3f6 > rightBounds[y])
|
||||
rightBounds[y] = var3f6;
|
||||
|
||||
var3e8 += var3ec;
|
||||
}
|
||||
}
|
||||
|
||||
while (shpImageTop <= shpImageBottom) {
|
||||
if (leftBounds[shpImageTop] > rightBounds[shpImageTop])
|
||||
shpImageTop++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
while (shpImageTop <= shpImageBottom) {
|
||||
if (leftBounds[shpImageBottom] > rightBounds[shpImageBottom])
|
||||
shpImageBottom--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
debug("Top: %d, Bot: %d", shpImageTop, shpImageBottom);
|
||||
if (shpImageTop <= shpImageBottom) {
|
||||
bool var3fa;
|
||||
if (r3->field1e == 2) {
|
||||
// TODO
|
||||
} else
|
||||
var3fa = (((r3->field24 * _starfieldPointDivisor) << 1) / 3 <= r3->field36.z);
|
||||
|
||||
if (!var3fa) {
|
||||
if (r3->field1e == 3) {
|
||||
// FIXME: is this used anywhere?
|
||||
uint16 var3fc = (_frameIndex << 3) ^ _frameIndex;
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
int16 xDiff = (int16)(dbl60 * 256);
|
||||
int16 yDiff = (int16)(dbl58 * 256);
|
||||
int16 var3f2 = (int16)(dbl50 * 256);
|
||||
int16 var3f4 = (int16)(dbl48 * 256);
|
||||
|
||||
int16 var3f6 = var3f2 * shpImageTop + (int16)(dbl40 * 256);
|
||||
int16 var3f8 = var3f4 * shpImageTop + (int16)(dbl38 * 256);
|
||||
|
||||
Bitmap tmpBitmap(256, 249);
|
||||
byte otherBuffer[256 * 256];
|
||||
|
||||
int16 bitmapWidth = bitmap->width;
|
||||
int16 bitmapHeight = bitmap->height;
|
||||
|
||||
if (bitmapHeight > 245)
|
||||
error("Shape height too big in drawR3Shape!");
|
||||
if (bitmapWidth > 252)
|
||||
error("Shape width too big in drawR3Shape!");
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
memset(otherBuffer + i * 256, 0, bitmapWidth + 4);
|
||||
for (int i = 0; i < 2; i++)
|
||||
memset(otherBuffer + (bitmapHeight + 2 + i) * 256, 0, bitmapWidth + 4);
|
||||
|
||||
for (int i = 0; i < bitmapHeight; i++) {
|
||||
otherBuffer[512 + i * 256 + 0] = 0;
|
||||
otherBuffer[512 + i * 256 + 1] = 0;
|
||||
otherBuffer[512 + i * 256 + bitmapWidth + 2] = 0;
|
||||
otherBuffer[512 + i * 256 + bitmapWidth + 3] = 0;
|
||||
}
|
||||
|
||||
if (r3->field1e == 2) {
|
||||
// TODO
|
||||
} else
|
||||
_gfx->copyRectBetweenBitmaps(&tmpBitmap, 2, 2, bitmap.get(), 0, 0, bitmapWidth, bitmapHeight);
|
||||
|
||||
byte *bgPixels = _gfx->getBackgroundPixels() + shpImageTop * SCREEN_WIDTH;
|
||||
|
||||
for (int y = shpImageTop; y <= shpImageBottom; y++) {
|
||||
int16 leftBound = leftBounds[y];
|
||||
int16 rowWidth = rightBounds[y] - leftBound;
|
||||
int16 srcX = leftBound * xDiff + var3f6;
|
||||
int16 srcY = leftBound * yDiff + var3f8;
|
||||
var3f6 += var3f2;
|
||||
var3f8 += var3f4;
|
||||
|
||||
byte *bgPixels2 = bgPixels + leftBound;
|
||||
bgPixels += SCREEN_WIDTH;
|
||||
|
||||
if (rowWidth == 0)
|
||||
continue;
|
||||
|
||||
debug("Width: %d", rowWidth);
|
||||
|
||||
if (var3fa) {
|
||||
srcX += 0x80;
|
||||
srcY += 0x80;
|
||||
|
||||
int16 cx = srcX;
|
||||
int16 bx = srcY;
|
||||
byte *di = bgPixels2;
|
||||
|
||||
for (int a = 0; a < rowWidth; a++) {
|
||||
byte b = tmpBitmap.pixels[(bx & 0xff00) + (cx >> 8)];
|
||||
cx += xDiff;
|
||||
bx += yDiff;
|
||||
if (b == 0)
|
||||
*(di++) = 8; // FIXME: shouldn't assign anything, fix after done testing
|
||||
else
|
||||
*(di++) = b;
|
||||
}
|
||||
} else {
|
||||
warning("Unimplemented branch in \"drawR3Shape\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r3->funcPtr2 != nullptr) {
|
||||
// TODO: call it
|
||||
}
|
||||
}
|
||||
|
||||
bool StarTrekEngine::sub_1c022(R3 *r3) {
|
||||
Point3 point = r3->field36;
|
||||
if (point.z < _flt_50898)
|
||||
return false;
|
||||
return true; // TODO: finish this properly
|
||||
}
|
||||
|
||||
Point3 StarTrekEngine::constructPoint3ForStarfield(int16 x, int16 y, int16 z) {
|
||||
@ -153,9 +510,8 @@ Point3 StarTrekEngine::matrixMult(const Matrix &weight, const Point3 &point) {
|
||||
Point3 p;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
p[i] = 0;
|
||||
for (int j = 0; j < 3; j++) { // FIXME: what is this weird multiplication?
|
||||
p[i] += (weight[i][j].raw() * (point[j] & 0xffff) << 2) >> 16;
|
||||
}
|
||||
for (int j = 0; j < 3; j++)
|
||||
p[i] += (int16)weight[i][j].multToInt(point[j]);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@ -164,13 +520,16 @@ Point3 StarTrekEngine::matrixMult(const Point3 &point, const Matrix &weight) {
|
||||
Point3 p = Point3();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
p[i] = 0;
|
||||
for (int j = 0; j < 3; j++) {
|
||||
p[i] += (weight[j][i].raw() * (point[j] & 0xffff) << 2) >> 16;
|
||||
}
|
||||
for (int j = 0; j < 3; j++)
|
||||
p[i] += (int16)weight[j][i].multToInt(point[j]);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int32 StarTrekEngine::scaleSpacePosition(int32 x, int32 z) {
|
||||
return (x * _starfieldPointDivisor) / z;
|
||||
}
|
||||
|
||||
Matrix StarTrekEngine::initMatrix() {
|
||||
Matrix mat;
|
||||
mat[0][0] = 1.0;
|
||||
@ -179,4 +538,17 @@ Matrix StarTrekEngine::initMatrix() {
|
||||
return mat;
|
||||
}
|
||||
|
||||
Matrix StarTrekEngine::initSpeedMatrixForXZMovement(Angle angle, const Matrix &matrix) {
|
||||
Fixed14 sinVal = sin(angle);
|
||||
Fixed14 cosVal = cos(angle);
|
||||
|
||||
Matrix matrix1 = initMatrix();
|
||||
matrix1[0].x = cosVal;
|
||||
matrix1[0].z = -sinVal;
|
||||
matrix1[2].x = sinVal;
|
||||
matrix1[2].z = cosVal;
|
||||
|
||||
return matrix * matrix1;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,6 +38,10 @@ struct TPoint {
|
||||
TPoint() : x(0), y(0), z(0) {}
|
||||
TPoint(T _x, T _y, T _z) : x(_x), y(_y), z(_z) {}
|
||||
|
||||
int32 getDiagonal() {
|
||||
return sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
TPoint<T> operator+(const TPoint<T> &p) const {
|
||||
TPoint<T> p2;
|
||||
p2.x = x + p.x;
|
||||
@ -52,6 +56,16 @@ struct TPoint {
|
||||
p2.z = z - p.z;
|
||||
return p2;
|
||||
}
|
||||
void operator+=(const TPoint &p) {
|
||||
x += p.x;
|
||||
y += p.y;
|
||||
z += p.z;
|
||||
}
|
||||
void operator-=(const TPoint &p) {
|
||||
x -= p.x;
|
||||
y -= p.y;
|
||||
z -= p.z;
|
||||
}
|
||||
T &operator[](int i) {
|
||||
if (i == 0)
|
||||
return x;
|
||||
@ -83,7 +97,11 @@ private:
|
||||
T m[3];
|
||||
|
||||
public:
|
||||
TMatrix() {}
|
||||
TMatrix() {
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 3; j++)
|
||||
m[i][j] = 0;
|
||||
}
|
||||
TMatrix(const TMatrix<T> &mat) {
|
||||
m[0] = mat.m[0];
|
||||
m[1] = mat.m[1];
|
||||
@ -96,6 +114,22 @@ public:
|
||||
return m[i];
|
||||
};
|
||||
|
||||
TMatrix operator*(const TMatrix &m2) const {
|
||||
TMatrix ret;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
ret[i][j] = 0;
|
||||
for (int a = 0; a < 3; a++)
|
||||
ret[i][j] += m[i][a] * m2[a][j];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void operator*=(const TMatrix &m2) {
|
||||
*this = *this * m2;
|
||||
}
|
||||
|
||||
TMatrix<T> invert() {
|
||||
TMatrix<T> ret;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
@ -124,7 +158,20 @@ struct R3 {
|
||||
int16 field22; // 0x22
|
||||
int16 field24; // 0x24
|
||||
Point3_Short speed; // 0x26
|
||||
int32 funcPtr1; // 0x2c
|
||||
int32 funcPtr2; // 0x30
|
||||
int16 field34; // 0x34
|
||||
Point3 field36; // 0x36
|
||||
Matrix matrix2; // 0x42
|
||||
int32 field54; // 0x54 (used for sorting by draw priority?)
|
||||
int16 field58; // 0x58
|
||||
int16 field5a; // 0x5a
|
||||
SharedPtr<FileStream> shpFile; // 0x68
|
||||
int16 bitmapOffset; // 0x6a
|
||||
double field80; // 0x80
|
||||
double field88; // 0x88
|
||||
double field90; // 0x90
|
||||
double field98; // 0x98
|
||||
};
|
||||
|
||||
// Maximum number of stars visible at once in the starfields
|
||||
|
@ -58,6 +58,7 @@ StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gam
|
||||
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound");
|
||||
DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics");
|
||||
DebugMan.addDebugChannel(kDebugSavegame, "savegame", "Savegames");
|
||||
DebugMan.addDebugChannel(kDebugSpace, "space", "Space and Pseudo-3D");
|
||||
|
||||
_gfx = nullptr;
|
||||
_sound = nullptr;
|
||||
@ -89,6 +90,8 @@ StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gam
|
||||
_roomIndexToLoad = 0;
|
||||
|
||||
_showSubtitles = true; // TODO: test
|
||||
Common::fill(_r3List, _r3List + NUM_SPACE_OBJECTS, (R3 *)nullptr);
|
||||
Common::fill(_orderedR3List, _orderedR3List + NUM_SPACE_OBJECTS, (R3 *)nullptr);
|
||||
|
||||
for (int i = 0; i < NUM_OBJECTS; i++)
|
||||
_itemList[i] = g_itemList[i];
|
||||
@ -221,8 +224,11 @@ void StarTrekEngine::playIntro() {
|
||||
//delR3(&_enterpriseR3); // TODO: uncomment
|
||||
|
||||
R3 planetR3 = R3();
|
||||
|
||||
// TODO: remainder of starfield initialization
|
||||
planetR3.matrix = initMatrix();
|
||||
planetR3.field1e = 3;
|
||||
planetR3.funcPtr1 = nullptr;
|
||||
planetR3.funcPtr2 = nullptr;
|
||||
planetR3.bitmapOffset = 0;
|
||||
|
||||
_gfx->clearScreenAndPriBuffer();
|
||||
_gfx->fadeoutScreen();
|
||||
@ -339,6 +345,16 @@ void StarTrekEngine::playIntro() {
|
||||
starfieldZoomSpeed = 0;
|
||||
break;
|
||||
|
||||
case 186:
|
||||
delR3(&_enterpriseR3);
|
||||
// TODO: the rest
|
||||
break;
|
||||
|
||||
case 366:
|
||||
planetR3.shpFile.reset();
|
||||
delR3(&planetR3);
|
||||
break;
|
||||
|
||||
case 378:
|
||||
_gfx->delSprite(&subtitleSprite);
|
||||
_byte_45b3c = 1;
|
||||
@ -371,23 +387,26 @@ void StarTrekEngine::initIntroR3ObjectToMove(R3 *r3, int16 srcAngle, int16 srcDe
|
||||
Fixed8 a1 = Fixed8::fromRaw((srcAngle << 8) / 90);
|
||||
Fixed8 a2 = Fixed8::fromRaw((destAngle << 8) / 90);
|
||||
|
||||
r3->pos.x = (sin(a1).multToInt(srcDepth) << 16) + _starfieldPosition.x;
|
||||
r3->pos.z = (cos(a1).multToInt(srcDepth) << 16) + _starfieldPosition.z;
|
||||
r3->pos.x = sin(a1).multToInt(srcDepth) + _starfieldPosition.x;
|
||||
r3->pos.z = cos(a1).multToInt(srcDepth) + _starfieldPosition.z;
|
||||
r3->pos.y = 0;
|
||||
|
||||
int32 deltaX = (sin(a2).multToInt(destDepth) << 16) + _starfieldPosition.x - r3->pos.x;
|
||||
int32 deltaZ = (cos(a2).multToInt(destDepth) << 16) + _starfieldPosition.z - r3->pos.z;
|
||||
int32 deltaX = sin(a2).multToInt(destDepth) + _starfieldPosition.x - r3->pos.x;
|
||||
int32 deltaZ = cos(a2).multToInt(destDepth) + _starfieldPosition.z - r3->pos.z;
|
||||
debug("Z: %d, %d", r3->pos.z - _starfieldPosition.z, cos(a2).multToInt(destDepth));
|
||||
|
||||
Fixed16 angle = atan2(deltaX, deltaZ);
|
||||
r3->matrix = initMatrix();
|
||||
Angle angle = atan2(deltaX, deltaZ);
|
||||
r3->matrix = initSpeedMatrixForXZMovement(angle, initMatrix());
|
||||
|
||||
// sub_248cc(angle, r3->matrix);
|
||||
debugCN(5, kDebugSpace, "initIntroR3ObjectToMove: pos %x,%x,%x; ", r3->pos.x, r3->pos.y, r3->pos.z);
|
||||
|
||||
if (ticks != 0) {
|
||||
debugC(5, kDebugSpace, "speed %x,%x,%x\n", r3->speed.x, r3->speed.y, r3->speed.z);
|
||||
r3->speed.x = deltaX / ticks;
|
||||
r3->speed.z = deltaZ / ticks;
|
||||
r3->speed.y = 0;
|
||||
} else {
|
||||
debugC(5, kDebugSpace, "speed 0\n");
|
||||
r3->speed.x = 0;
|
||||
r3->speed.z = 0;
|
||||
r3->speed.y = 0;
|
||||
|
@ -112,7 +112,8 @@ enum StarTrekGameFeatures {
|
||||
enum kDebugLevels {
|
||||
kDebugSound = 1 << 0,
|
||||
kDebugGraphics = 1 << 1,
|
||||
kDebugSavegame = 2 << 1
|
||||
kDebugSavegame = 1 << 2,
|
||||
kDebugSpace = 2 << 3
|
||||
};
|
||||
|
||||
enum GameMode {
|
||||
@ -215,9 +216,9 @@ public:
|
||||
/**
|
||||
* Unit of the angle is "quadrants" (90 degrees = 1.0)
|
||||
*/
|
||||
Fixed14 sin(Fixed8 angle);
|
||||
Fixed14 cos(Fixed8 angle);
|
||||
Fixed8 atan2(int32 deltaX, int32 deltaZ);
|
||||
Fixed14 sin(Angle angle);
|
||||
Fixed14 cos(Angle angle);
|
||||
Angle atan2(int32 deltaX, int32 deltaZ);
|
||||
|
||||
// Game modes
|
||||
Common::Error runGameMode(int mode);
|
||||
@ -264,15 +265,20 @@ private:
|
||||
void clearStarfieldPixels();
|
||||
void drawStarfield();
|
||||
void updateStarfieldAndShips(bool arg0);
|
||||
R3 *sub_19f24(R3 *r3);
|
||||
void drawR3Shape(R3 *r3);
|
||||
bool sub_1c022(R3 *r3);
|
||||
|
||||
Point3 constructPoint3ForStarfield(int16 x, int16 y, int16 z);
|
||||
Point3 matrixMult(const Matrix &weight, const Point3 &point);
|
||||
Point3 matrixMult(const Point3 &point, const Matrix &weight);
|
||||
int32 scaleSpacePosition(int32 x, int32 z);
|
||||
|
||||
/**
|
||||
* Creates something like an "identity" matrix? (Value 0x4000 along the diagonal)
|
||||
*/
|
||||
Matrix initMatrix();
|
||||
Matrix initSpeedMatrixForXZMovement(Angle angle, const Matrix &matrix);
|
||||
|
||||
// Transporter room
|
||||
void runTransportSequence(const Common::String &name);
|
||||
@ -542,8 +548,10 @@ public:
|
||||
Common::Rect _starfieldRect;
|
||||
R3 _enterpriseR3;
|
||||
R3 *_r3List[NUM_SPACE_OBJECTS];
|
||||
R3 *_orderedR3List[NUM_SPACE_OBJECTS];
|
||||
Matrix _starPositionMatrix;
|
||||
Matrix _someMatrix;
|
||||
float _flt_50898;
|
||||
|
||||
Graphics *_gfx;
|
||||
Sound *_sound;
|
||||
|
Loading…
x
Reference in New Issue
Block a user