aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorMatthew Stewart2018-05-13 01:40:31 -0400
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commit4927cd90b7c6d5f1dc7b3eaeb44502e251f7257c (patch)
tree5471597ff83ae4f6d9de10e8eac93955814efe99 /engines
parent612cf7bdbe599d2adbbad62e33f5fcb73de3d58d (diff)
downloadscummvm-rg350-4927cd90b7c6d5f1dc7b3eaeb44502e251f7257c.tar.gz
scummvm-rg350-4927cd90b7c6d5f1dc7b3eaeb44502e251f7257c.tar.bz2
scummvm-rg350-4927cd90b7c6d5f1dc7b3eaeb44502e251f7257c.zip
STARTREK: Bitmap scaling
Diffstat (limited to 'engines')
-rw-r--r--engines/startrek/events.cpp2
-rw-r--r--engines/startrek/startrek.cpp171
-rw-r--r--engines/startrek/startrek.h6
3 files changed, 161 insertions, 18 deletions
diff --git a/engines/startrek/events.cpp b/engines/startrek/events.cpp
index 02b0112136..354dfb1c77 100644
--- a/engines/startrek/events.cpp
+++ b/engines/startrek/events.cpp
@@ -53,6 +53,8 @@ void StarTrekEngine::pollSystemEvents() {
int delay = 1000/18.206 - (_system->getMillis() - _frameStartMillis);
_clockTicks++;
+ if (delay < 0)
+ debug(5, "Late frame");
while (delay < 0) { // Check if we're behind...
delay += 1000/18.206;
_clockTicks++;
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index 3acd3d9c8a..3a434bf171 100644
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -229,7 +229,7 @@ void StarTrekEngine::runTransportSequence(const Common::String &name) {
Common::String filename = getCrewmanAnimFilename(i, name);
int x = crewmanTransportPositions[i][0];
int y = crewmanTransportPositions[i][1];
- loadAnimationForObject(i, filename, x, y, 256);
+ loadAnimationForObject(i, filename, x, y, 128);
_objectList[i].animationString[0] = '\0';
}
@@ -358,7 +358,7 @@ void StarTrekEngine::initObjects() {
strcpy(_redshirtObject->animationString, "rstnd");
}
-int StarTrekEngine::loadAnimationForObject(int objectIndex, const Common::String &animName, uint16 x, uint16 y, uint16 arg8) {
+int StarTrekEngine::loadAnimationForObject(int objectIndex, const Common::String &animName, uint16 x, uint16 y, uint16 scale) {
debugC(6, kDebugGraphics, "Load animation '%s' on object %d", animName.c_str(), objectIndex);
Object *object;
@@ -371,10 +371,10 @@ int StarTrekEngine::loadAnimationForObject(int objectIndex, const Common::String
if (object->spriteDrawn) {
releaseAnim(object);
- drawObjectToScreen(object, animName, x, y, arg8, false);
+ drawObjectToScreen(object, animName, x, y, scale, false);
}
else {
- drawObjectToScreen(object, animName, x, y, arg8, true);
+ drawObjectToScreen(object, animName, x, y, scale, true);
}
object->field64 = 0;
@@ -425,8 +425,8 @@ void StarTrekEngine::updateObjectAnimations() {
object->animFile->read(animFrameFilename, 16);
sprite->setBitmap(loadAnimationFrame(animFrameFilename, object->scale));
- memset(object->animationString4, 0, 16);
- strncpy(object->animationString4, animFrameFilename, 15);
+ memset(object->animationString4, 0, 10);
+ strncpy(object->animationString4, animFrameFilename, 9);
object->animFile->seek(10 + object->animFrame * 22, SEEK_SET);
uint16 xOffset = object->animFile->readUint16();
@@ -481,7 +481,7 @@ void StarTrekEngine::objectFunc1() {
}
}
-void StarTrekEngine::drawObjectToScreen(Object *object, const Common::String &_animName, uint16 x, uint16 y, uint16 arg8, bool addSprite) {
+void StarTrekEngine::drawObjectToScreen(Object *object, const Common::String &_animName, uint16 x, uint16 y, uint16 scale, bool addSprite) {
Common::String animFilename = _animName;
if (_animName.hasPrefixIgnoreCase("stnd") /* && word_45d20 == -1 */) // TODO
animFilename += 'j';
@@ -494,7 +494,7 @@ void StarTrekEngine::drawObjectToScreen(Object *object, const Common::String &_a
object->field5e = x;
object->field60 = y;
object->field62 = 0;
- object->scale = arg8;
+ object->scale = scale;
object->animFile->seek(16, SEEK_SET);
object->frameToStartNextAnim = object->animFile->readUint16() + _frameIndex;
@@ -507,11 +507,11 @@ void StarTrekEngine::drawObjectToScreen(Object *object, const Common::String &_a
if (addSprite)
_gfx->addSprite(sprite);
- sprite->setBitmap(loadAnimationFrame(firstFrameFilename, arg8));
+ sprite->setBitmap(loadAnimationFrame(firstFrameFilename, scale));
memset(object->animationString4, 0, sizeof(char) * 10);
strncpy(object->animationString4, firstFrameFilename, sizeof(char) * 9);
- object->scale = arg8;
+ object->scale = scale;
object->animFile->seek(10, SEEK_SET);
uint16 xOffset = object->animFile->readUint16();
@@ -544,7 +544,7 @@ void StarTrekEngine::releaseAnim(Object *object) {
object->spriteDrawn = 0;
}
-SharedPtr<Bitmap> StarTrekEngine::loadAnimationFrame(const Common::String &filename, uint16 arg2) {
+SharedPtr<Bitmap> StarTrekEngine::loadAnimationFrame(const Common::String &filename, uint16 scale) {
SharedPtr<Bitmap> bitmapToReturn;
char basename[5];
@@ -633,9 +633,8 @@ SharedPtr<Bitmap> StarTrekEngine::loadAnimationFrame(const Common::String &filen
bitmapToReturn = _gfx->loadBitmap(filename);
}
- if (arg2 != 256) {
- // TODO
- // bitmapToReturn = scaleBitmap(bitmapToReturn, arg2);
+ if (scale != 256) {
+ bitmapToReturn = scaleBitmap(bitmapToReturn, scale);
}
return bitmapToReturn;
@@ -647,10 +646,148 @@ Common::String StarTrekEngine::getCrewmanAnimFilename(int objectIndex, const Com
return crewmanChars[objectIndex] + basename;
}
-void StarTrekEngine::updateClockTicks() {
- // TODO (based on DOS interrupt 1A, AH=0; read system clock counter)
+/**
+ * A scale of 256 is the baseline.
+ */
+SharedPtr<Bitmap> StarTrekEngine::scaleBitmap(SharedPtr<Bitmap> bitmap, uint16 scale) {
+ int scaledWidth = (bitmap->width * scale) >> 8;
+ int scaledHeight = (bitmap->height * scale) >> 8;
+ int origWidth = bitmap->width;
+ int origHeight = bitmap->height;
+
+ if (scaledWidth < 1)
+ scaledWidth = 1;
+ if (scaledHeight < 1)
+ scaledHeight = 1;
+
+ SharedPtr<Bitmap> scaledBitmap(new Bitmap(scaledWidth, scaledHeight));
+ scaledBitmap->xoffset = (bitmap->xoffset * scale) >> 8;
+ scaledBitmap->yoffset = (bitmap->yoffset * scale) >> 8;
+
+ // sub_344a5(scaledWidth, origWidth);
+
+ origHeight--;
+ scaledHeight--;
+
+ byte *src = bitmap->pixels;
+ byte *dest = scaledBitmap->pixels;
+
+ if (scale <= 256) {
+ int16 var2e = 0;
+ uint16 var30 = scaledHeight << 1;
+ uint16 var32 = (scaledHeight - origHeight) << 1;
+ uint16 origRow = 0;
+
+ while (origRow <= origHeight) {
+ if (var2e < 0) {
+ var2e += var30;
+ }
+ else {
+ var2e += var32;
+ scaleBitmapRow(src, dest, origWidth, scaledWidth);
+ dest += scaledWidth;
+ }
- _clockTicks = 0;
+ src += bitmap->width;
+ origRow++;
+ }
+ }
+ else {
+ int16 var2e = (origHeight << 1) - scaledHeight;
+ uint16 var30 = origHeight << 1;
+ uint16 var32 = (origHeight - scaledHeight) << 1;
+ uint16 srcRowChanged = true;
+ origWidth = bitmap->width;
+ uint16 scaledRow = 0;
+ byte *rowData = new byte[scaledWidth];
+
+ while (scaledRow++ <= scaledHeight) {
+ if (srcRowChanged) {
+ scaleBitmapRow(src, rowData, origWidth, scaledWidth);
+ srcRowChanged = false;
+ }
+
+ memcpy(dest, rowData, scaledWidth);
+ dest += scaledWidth;
+
+ if (var2e < 0) {
+ var2e += var30;
+ }
+ else {
+ var2e += var32;
+ src += origWidth;
+ srcRowChanged = true;
+ }
+ }
+
+ delete[] rowData;
+ }
+
+ return scaledBitmap;
+}
+
+/**
+ * This was heavily optimized in the original game (manually constructed an unrolled
+ * loop).
+ */
+void StarTrekEngine::scaleBitmapRow(byte *src, byte *dest, uint16 origWidth, uint16 scaledWidth) {
+ if (origWidth >= scaledWidth) {
+ int16 var2 = (scaledWidth << 1) - origWidth;
+ uint16 var4 = scaledWidth << 1;
+ uint16 var6 = (scaledWidth - origWidth) << 1;
+ uint16 varE = 0;
+ uint16 varA = 0;
+ uint16 var8 = origWidth;
+ uint16 di = 0;
+
+ while (var8-- != 0) {
+ if (var2 < 0) {
+ var2 += var4;
+ }
+ else {
+ var2 += var6;
+ if (di != 0) {
+ if (varE != 0) {
+ *(dest - 1) = *src++;
+ varE = 0;
+ di--;
+ }
+ src += di;
+ di = 0;
+ }
+ *dest++ = *src;
+ varE = 1;
+ }
+
+ di++;
+ varA++;
+ }
+ }
+ else {
+ int16 var2 = ((origWidth - 1) << 1) - (scaledWidth - 1);
+ uint16 var4 = (origWidth - 1) << 1;
+ uint16 var6 = ((origWidth - 1) - (scaledWidth - 1)) << 1;
+ uint16 varA = 0;
+ uint16 var8 = scaledWidth;
+ uint16 di = 0;
+
+ while (var8-- != 0) {
+ if (di != 0) {
+ src += di;
+ di = 0;
+ }
+ *dest++ = *src;
+
+ if (var2 < 0)
+ var2 += var4;
+ else {
+ var2 += var6;
+ di++;
+ }
+
+ varA++;
+ }
+ }
}
/**
diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h
index 921d655f38..67c2c8080f 100644
--- a/engines/startrek/startrek.h
+++ b/engines/startrek/startrek.h
@@ -132,6 +132,8 @@ public:
SharedPtr<Bitmap> loadAnimationFrame(const Common::String &filename, uint16 arg2);
Common::String getCrewmanAnimFilename(int objectIndex, const Common::String &basename);
+ SharedPtr<Bitmap> scaleBitmap(SharedPtr<Bitmap> bitmap, uint16 scale);
+ void scaleBitmapRow(byte *src, byte *dest, uint16 origWidth, uint16 scaledWidth);
// Events
public:
@@ -142,7 +144,6 @@ public:
bool popNextEvent(TrekEvent *e);
void addEventToQueue(const TrekEvent &e);
void clearEventBuffer();
- uint32 getClockTicks();
void updateEvents();
void updateTimerEvent();
void updateMouseEvents();
@@ -190,6 +191,9 @@ public:
SharedPtr<FileStream> _objectBanFiles[MAX_OBJECTS / 2];
uint16 _objectBanVar2[MAX_OBJECTS / 2]; // TODO: initialize?
+
+ // _clockTicks is based on DOS interrupt 1A, AH=0; read system clock counter.
+ // Updates 18.206 times every second.
uint32 _clockTicks;
uint32 _frameIndex;