XEEN: Converted SpriteResource to decoding sprite frames on the fly

This commit is contained in:
Paul Gilbert 2014-12-26 18:31:05 +11:00
parent 4f423c74b7
commit d213db3dc1
7 changed files with 80 additions and 101 deletions

View File

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

View File

@ -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<uint32> 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

View File

@ -55,17 +55,23 @@ public:
class SpriteResource {
private:
Common::Array<XSurface> _frames;
struct IndexEntry {
uint16 _offset1, _offset2;
};
Common::Array<IndexEntry> _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

View File

@ -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<Common::Rect>::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();
}
}

View File

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

View File

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

View File

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