From d213db3dc1b24e281e03dc593f21925db8fcd10e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 26 Dec 2014 18:31:05 +1100 Subject: [PATCH] XEEN: Converted SpriteResource to decoding sprite frames on the fly --- engines/xeen/darkside/darkside_game.cpp | 7 +-- engines/xeen/resources.cpp | 81 ++++++++++--------------- engines/xeen/resources.h | 14 +++-- engines/xeen/screen.cpp | 18 ++---- engines/xeen/screen.h | 6 +- engines/xeen/xsurface.cpp | 43 +++++++------ engines/xeen/xsurface.h | 12 ++-- 7 files changed, 80 insertions(+), 101 deletions(-) diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index 728e15595f0..a597ab2ce84 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -59,11 +59,10 @@ void DarkSideEngine::darkSideIntro() { bool breakFlag = false; int nwcIndex = 0, nwcFrame = 0; - for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) { + for (int idx = 0; idx < 55 && !shouldQuit() && !breakFlag; ++idx) { _events->updateGameCounter(); _screen->vertMerge(0); - const XSurface &frame = nwc[nwcIndex].getFrame(nwcFrame); - _screen->transBlitFrom(frame, Common::Point(0, 0)); + nwc[nwcIndex].draw(*_screen, nwcFrame, Common::Point(0, 0)); _screen->draw(); switch (idx) { @@ -91,8 +90,6 @@ void DarkSideEngine::darkSideIntro() { } } } - - } } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index b005d7431d0..4cc586f014b 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -217,70 +217,45 @@ void File::openFile(const Common::String &filename) { /*------------------------------------------------------------------------*/ SpriteResource::SpriteResource(const Common::String &filename) { + // Open the resource File f(filename); // Read in the index int count = f.readUint16LE(); - Common::Array index; - index.resize(count); - for (int i = 0; i < count; ++i) - index[i] = f.readUint32LE(); - - // Process each shape - _frames.resize(count); - for (int i = 0; i < count; ++i) { - uint16 cell1 = index[i] & 0xffff, cell2 = index[i] >> 16; - assert(cell1); + _index.resize(count); - setFrameSize(f, cell1, cell2, _frames[i]); - decodeFrame(f, cell1, _frames[i]); - decodeFrame(f, cell2, _frames[i]); + for (int i = 0; i < count; ++i) { + _index[i]._offset1 = f.readUint16LE(); + _index[i]._offset2 = f.readUint16LE(); } + + // Read in a copy of the file + _filesize = f.size(); + _data = new byte[_filesize]; + f.seek(0); + f.read(_data, _filesize); +} + +SpriteResource::~SpriteResource() { + delete[] _data; } int SpriteResource::size() const { - return _frames.size(); + return _index.size(); } -const XSurface &SpriteResource::getFrame(int frame) { - return _frames[frame]; +void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { + drawOffset(dest, _index[frame]._offset1, destPos); + if (_index[frame]._offset2) + drawOffset(dest, _index[frame]._offset2, destPos); } -void SpriteResource::setFrameSize(File &f, uint16 offset1, uint16 offset2, XSurface &s) { - int maxWidth = 0, maxHeight = 0; - - // Check each of the two cells for the frame for their sizes - for (int i = 0; i < 2; ++i) { - uint16 offset = (i == 0) ? offset1 : offset2; - if (!offset) - break; - - // Get the cell dimensions - f.seek(offset); - int x = f.readUint16LE(); - int w = f.readUint16LE(); - int y = f.readUint16LE(); - int h = f.readUint16LE(); - - // Check for total size of the frame - if ((x + w) > maxWidth) - maxWidth = x + w; - if ((y + h) > maxHeight) - maxHeight = x + h; - } - - // Create the surface - s.create(maxWidth, maxHeight); - - // Empty the surface - s.fillRect(Common::Rect(0, 0, maxWidth, maxHeight), 0); -} - -void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { +void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { // Get cell header + Common::MemoryReadStream f(_data, _filesize); f.seek(offset); int xOffset = f.readUint16LE(); - f.skip(2); + int width = f.readUint16LE(); int yOffset = f.readUint16LE(); int height = f.readUint16LE(); @@ -300,7 +275,7 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { } else { // Skip the transparent pixels at the beginning of the scan line int xPos = f.readByte() + xOffset; ++byteCount; - byte *destP = (byte *)s.getBasePtr(xPos, yPos); + byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos); while (byteCount < lineLength) { // The next byte is an opcode that determines what @@ -314,8 +289,9 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { switch (cmd) { case 0: // The following len + 1 bytes are stored as indexes into the color table. case 1: // The following len + 33 bytes are stored as indexes into the color table. - for (int i = 0; i < opcode + 1; ++i, ++xPos) + for (int i = 0; i < opcode + 1; ++i, ++xPos) { *destP++ = f.readByte(); ++byteCount; + } break; case 2: // The following byte is an index into the color table, draw it len + 3 times. @@ -364,8 +340,13 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { break; } } + + assert(byteCount == lineLength); } } + + dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, + destPos.x + xOffset + width, destPos.y + yOffset + height)); } } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 1c55cc8889b..fcb184277a6 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -55,17 +55,23 @@ public: class SpriteResource { private: - Common::Array _frames; + struct IndexEntry { + uint16 _offset1, _offset2; + }; + Common::Array _index; - void setFrameSize(File &f, uint16 offset1, uint16 offset2, XSurface &s); + int32 _filesize; + byte *_data; - void decodeFrame(File &f, uint16 offset, XSurface &s); + void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const; public: SpriteResource(const Common::String &filename); + ~SpriteResource(); + int size() const; - const XSurface &getFrame(int frame); + void draw(XSurface &dest, int frame, const Common::Point &destPos) const; }; } // End of namespace Xeen diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 65f96002207..0c7df8b776f 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -33,6 +33,7 @@ namespace Xeen { */ Screen::Screen(XeenEngine *vm) : _vm(vm) { _fadeMode = false; + create(SCREEN_WIDTH, SCREEN_HEIGHT); } void Screen::update() { @@ -57,16 +58,6 @@ void Screen::addDirtyRect(const Common::Rect &r) { _dirtyRects.push_back(r); } -void Screen::transBlitFrom(const XSurface &src, const Common::Point &destPos) { - XSurface::transBlitFrom(src, destPos); - addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src.w, destPos.y + src.h)); -} - -void Screen::blitFrom(const XSurface &src, const Common::Point &destPos) { - XSurface::blitFrom(src, destPos); - addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src.w, destPos.y + src.h)); -} - void Screen::mergeDirtyRects() { Common::List::iterator rOuter, rInner; @@ -110,7 +101,8 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co */ void Screen::loadPalette(const Common::String &name) { File f(name); - f.read(_tempPaltte, PALETTE_SIZE); + for (int i = 0; i < PALETTE_SIZE; ++i) + _tempPaltte[i] = f.readByte() << 2; } /** @@ -133,7 +125,7 @@ void Screen::loadPage(int pageNum) { _pages[1].create(SCREEN_WIDTH, SCREEN_HEIGHT); } - _pages[pageNum].blitFrom(*this); + blitTo(_pages[pageNum]); } /** @@ -217,6 +209,8 @@ void Screen::fadeInner(int step) { updatePalette(); } + + _vm->_events->pollEventsAndWait(); } } diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 3359af8336c..02fe74607c6 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -59,16 +59,12 @@ private: void updatePalette(const byte *pal, int start, int count16); public: - virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos); - - virtual void blitFrom(const XSurface &src, const Common::Point &destPos); + virtual void addDirtyRect(const Common::Rect &r); public: Screen(XeenEngine *vm); void update(); - void addDirtyRect(const Common::Rect &r); - void loadPalette(const Common::String &name); void loadBackground(const Common::String &name); diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index b5f08f4603f..f63ad14350f 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -20,6 +20,7 @@ * */ +#include "common/algorithm.h" #include "xeen/xsurface.h" namespace Xeen { @@ -39,41 +40,43 @@ void XSurface::create(uint16 w, uint16 h) { Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8()); } -void XSurface::transBlitFrom(const XSurface &src) { - transBlitFrom(src, Common::Point()); +void XSurface::transBlitTo(XSurface &dest) const { + transBlitTo(dest, Common::Point()); } -void XSurface::blitFrom(const XSurface &src) { - blitFrom(src, Common::Point()); +void XSurface::blitTo(XSurface &dest) const { + blitTo(dest, Common::Point()); } -void XSurface::transBlitFrom(const XSurface &src, const Common::Point &destPos) { - if (getPixels() == nullptr) - create(w, h); +void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos) const { + if (dest.getPixels() == nullptr) + dest.create(w, h); - for (int yp = 0; yp < src.h; ++yp) { - const byte *srcP = (const byte *)src.getBasePtr(0, yp); - byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp); + for (int yp = 0; yp < h; ++yp) { + const byte *srcP = (const byte *)getBasePtr(0, yp); + byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y + yp); - for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) { + for (int xp = 0; xp < w; ++xp, ++srcP, ++destP) { if (*srcP != 0) *destP = *srcP; } } + + dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y)); } -void XSurface::blitFrom(const XSurface &src, const Common::Point &destPos) { - if (getPixels() == nullptr) - create(w, h); +void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const { + if (dest.getPixels() == nullptr) + dest.create(w, h); - for (int yp = 0; yp < src.h; ++yp) { - const byte *srcP = (const byte *)src.getBasePtr(0, yp); - byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp); + for (int yp = 0; yp < h; ++yp) { + const byte *srcP = (const byte *)getBasePtr(0, yp); + byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y + yp); - for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) { - *destP = *srcP; - } + Common::copy(srcP, srcP + w, destP); } + + dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y)); } } // End of namespace Xeen diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index c2d6e78d8d5..92f1236349e 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -32,9 +32,7 @@ namespace Xeen { class XSurface: public Graphics::Surface { public: - virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos); - - virtual void blitFrom(const XSurface &src, const Common::Point &destPos); + virtual void addDirtyRect(const Common::Rect &r) {} public: XSurface(); XSurface(int w, int h); @@ -42,9 +40,13 @@ public: void create(uint16 w, uint16 h); - void transBlitFrom(const XSurface &src); + void transBlitTo(XSurface &dest) const; - void blitFrom(const XSurface &src); + void transBlitTo(XSurface &dest, const Common::Point &destPos) const; + + void blitTo(XSurface &dest, const Common::Point &destPos) const; + + void blitTo(XSurface &dest) const; bool empty() const { return getPixels() == nullptr; } };