diff options
author | Matthew Stewart | 2018-05-13 01:40:31 -0400 |
---|---|---|
committer | Eugene Sandulenko | 2018-08-09 08:37:30 +0200 |
commit | 4927cd90b7c6d5f1dc7b3eaeb44502e251f7257c (patch) | |
tree | 5471597ff83ae4f6d9de10e8eac93955814efe99 /engines | |
parent | 612cf7bdbe599d2adbbad62e33f5fcb73de3d58d (diff) | |
download | scummvm-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.cpp | 2 | ||||
-rw-r--r-- | engines/startrek/startrek.cpp | 171 | ||||
-rw-r--r-- | engines/startrek/startrek.h | 6 |
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; |