SUPERNOVA: Buffers sections of image on init

This commit is contained in:
Joseph-Eugene Winzer 2017-06-28 14:09:13 +02:00 committed by Thierry Crozat
parent 1ae1134706
commit ef1bbce68e
3 changed files with 81 additions and 78 deletions

View file

@ -33,8 +33,7 @@
namespace Supernova { namespace Supernova {
MSNImageDecoder::MSNImageDecoder() MSNImageDecoder::MSNImageDecoder()
: _surface(NULL) : _palette(NULL)
, _palette(NULL)
, _encodedImage(NULL) { , _encodedImage(NULL) {
} }
@ -133,77 +132,73 @@ bool MSNImageDecoder::loadStream(Common::SeekableReadStream &stream) {
} }
} }
loadSections();
return true; return true;
} }
bool MSNImageDecoder::loadSection(int section) { bool MSNImageDecoder::loadSections() {
int imageWidth = 320; bool isNewspaper = _filenumber == 1 || _filenumber == 2;
int imageHeight = 200; int imageWidth = isNewspaper ? 640 : 320;
int imageHeight = isNewspaper ? 480 : 200;
_pitch = imageWidth;
if (_surface) for (int section = 0; section < _numSections; ++section) {
_surface->free(); Graphics::Surface *surface = new Graphics::Surface;
_sectionSurfaces.push_back(surface);
surface->create(imageWidth,
imageHeight,
g_system->getScreenFormat());
byte *surfacePixels = static_cast<byte *>(surface->getPixels());
_surface = new Graphics::Surface; if (isNewspaper) {
for (int i = 0; i < imageWidth * imageHeight / 8; ++i) {
if (_filenumber == 1 || _filenumber == 2) { *surfacePixels++ = (_encodedImage[i] & 0x80) ? kColorWhite63 : kColorBlack;
imageWidth = 640; *surfacePixels++ = (_encodedImage[i] & 0x40) ? kColorWhite63 : kColorBlack;
imageHeight = 480; *surfacePixels++ = (_encodedImage[i] & 0x20) ? kColorWhite63 : kColorBlack;
_pitch = 640; *surfacePixels++ = (_encodedImage[i] & 0x10) ? kColorWhite63 : kColorBlack;
*surfacePixels++ = (_encodedImage[i] & 0x08) ? kColorWhite63 : kColorBlack;
_surface->create(imageWidth, imageHeight, g_system->getScreenFormat()); *surfacePixels++ = (_encodedImage[i] & 0x04) ? kColorWhite63 : kColorBlack;
byte *surfacePixels = static_cast<byte *>(_surface->getPixels()); *surfacePixels++ = (_encodedImage[i] & 0x02) ? kColorWhite63 : kColorBlack;
for (int i = 0; i < imageWidth * imageHeight / 8; ++i) { *surfacePixels++ = (_encodedImage[i] & 0x01) ? kColorWhite63 : kColorBlack;
*surfacePixels++ = (_encodedImage[i] & 0x80) ? kColorWhite63 : kColorBlack; }
*surfacePixels++ = (_encodedImage[i] & 0x40) ? kColorWhite63 : kColorBlack;
*surfacePixels++ = (_encodedImage[i] & 0x20) ? kColorWhite63 : kColorBlack;
*surfacePixels++ = (_encodedImage[i] & 0x10) ? kColorWhite63 : kColorBlack;
*surfacePixels++ = (_encodedImage[i] & 0x08) ? kColorWhite63 : kColorBlack;
*surfacePixels++ = (_encodedImage[i] & 0x04) ? kColorWhite63 : kColorBlack;
*surfacePixels++ = (_encodedImage[i] & 0x02) ? kColorWhite63 : kColorBlack;
*surfacePixels++ = (_encodedImage[i] & 0x01) ? kColorWhite63 : kColorBlack;
}
} else {
_pitch = 320;
_surface->create(imageWidth, imageHeight, g_system->getScreenFormat());
byte *surfacePixels = static_cast<byte *>(_surface->getPixels());
const uint32 kInvalidAddress = 0x00FFFFFF;
uint image = section;
if (image < 128) {
do {
uint32 offset = (_section[image].addressHigh << 16) + _section[image].addressLow;
if (offset == kInvalidAddress || _section[image].x2 == 0) {
return false;
}
int width = _section[image].x2 - _section[image].x1 + 1;
int height = _section[image].y2 - _section[image].y1 + 1;
uint32 destAddress = imageWidth * _section[image].y1 + _section[image].x1;
while (height) {
Common::copy(_encodedImage + offset, _encodedImage + offset + width, surfacePixels + destAddress);
offset += width;
destAddress += imageWidth;
--height;
}
image = _section[image].next;
} while (image != 0);
} else { } else {
image -= 128; uint image = section;
do { if (image < 128) {
int width = _section[image].x2 - _section[image].x1 + 1; do {
int height = _section[image].y2 - _section[image].y1 + 1; uint32 offset = (_section[image].addressHigh << 16) + _section[image].addressLow;
uint32 destAddress = imageWidth * _section[image].y1 + _section[image].x1; if (offset == kInvalidAddress || _section[image].x2 == 0) {
uint32 offset = (_section[image].addressHigh << 16) + _section[image].addressLow + destAddress; return false;
while (height) { }
Common::copy(_encodedImage + offset, _encodedImage + offset + width, surfacePixels + destAddress); int width = _section[image].x2 - _section[image].x1 + 1;
offset += imageWidth; int height = _section[image].y2 - _section[image].y1 + 1;
destAddress += imageWidth; uint32 destAddress = imageWidth * _section[image].y1 + _section[image].x1;
--height; while (height) {
} Common::copy(_encodedImage + offset, _encodedImage + offset + width, surfacePixels + destAddress);
offset += width;
destAddress += imageWidth;
--height;
}
image = _section[image].next; image = _section[image].next;
} while (image != 0); } while (image != 0);
} else {
image -= 128;
do {
int width = _section[image].x2 - _section[image].x1 + 1;
int height = _section[image].y2 - _section[image].y1 + 1;
uint32 destAddress = imageWidth * _section[image].y1 + _section[image].x1;
uint32 offset = (_section[image].addressHigh << 16) + _section[image].addressLow + destAddress;
while (height) {
Common::copy(_encodedImage + offset, _encodedImage + offset + width, surfacePixels + destAddress);
offset += imageWidth;
destAddress += imageWidth;
--height;
}
image = _section[image].next;
} while (image != 0);
}
} }
} }
@ -215,14 +210,14 @@ void MSNImageDecoder::destroy() {
delete[] _palette; delete[] _palette;
_palette = NULL; _palette = NULL;
} }
if (_surface) {
_surface->free();
_surface = NULL;
}
if (_encodedImage) { if (_encodedImage) {
delete[] _encodedImage; delete[] _encodedImage;
_encodedImage = NULL; _encodedImage = NULL;
} }
for (Common::Array<Graphics::Surface *>::iterator it = _sectionSurfaces.begin();
it != _sectionSurfaces.end(); ++it) {
(*it)->free();
}
} }
} }

View file

@ -43,20 +43,20 @@ public:
virtual void destroy(); virtual void destroy();
virtual bool loadStream(Common::SeekableReadStream &stream); virtual bool loadStream(Common::SeekableReadStream &stream);
virtual const Graphics::Surface *getSurface() const { return _surface; } virtual const Graphics::Surface *getSurface() const { return _sectionSurfaces[0]; }
virtual const byte *getPalette() const { return _palette; } virtual const byte *getPalette() const { return _palette; }
bool loadSection(int section);
bool init(int filenumber); bool init(int filenumber);
static const int kMaxSections = 50; static const int kMaxSections = 50;
static const int kMaxClickFields = 80; static const int kMaxClickFields = 80;
static const uint32 kInvalidAddress = 0x00FFFFFF;
int _filenumber; int _filenumber;
int _pitch; int _pitch;
int _numSections; int _numSections;
int _numClickFields; int _numClickFields;
Graphics::Surface *_surface; Common::Array<Graphics::Surface *> _sectionSurfaces;
byte *_palette; byte *_palette;
byte *_encodedImage; byte *_encodedImage;
@ -77,6 +77,9 @@ public:
byte y2; byte y2;
byte next; byte next;
} _clickField[kMaxClickFields]; } _clickField[kMaxClickFields];
private:
bool loadSections();
}; };
} }

View file

@ -267,18 +267,20 @@ void SupernovaEngine::playSoundMod(int filenumber)
} }
void SupernovaEngine::renderImage(MSNImageDecoder &image, int section, bool fullscreen) { void SupernovaEngine::renderImage(MSNImageDecoder &image, int section, bool fullscreen) {
if (section > image._numSections - 1)
return;
_currentImage = &image; _currentImage = &image;
_imageIndex = image._filenumber; _imageIndex = image._filenumber;
_sectionIndex = section; _sectionIndex = section;
image.loadSection(section);
_system->getPaletteManager()->setPalette(image.getPalette(), 16, 239); _system->getPaletteManager()->setPalette(image.getPalette(), 16, 239);
paletteBrightness(); paletteBrightness();
Common::Rect sectionRect(image._section[section].x1, Common::Rect sectionRect(image._section[section].x1,
image._section[section].y1, image._section[section].y1,
image._section[section].x2 - image._section[section].x1, image._section[section].x2,
image._section[section].y2 - image._section[section].y1); image._section[section].y2);
if (image._filenumber == 1 || image._filenumber == 2) { if (image._filenumber == 1 || image._filenumber == 2) {
sectionRect.setWidth(640); sectionRect.setWidth(640);
sectionRect.setHeight(480); sectionRect.setHeight(480);
@ -297,11 +299,11 @@ void SupernovaEngine::renderImage(MSNImageDecoder &image, int section, bool full
} }
if (fullscreen) { if (fullscreen) {
_system->copyRectToScreen(image.getSurface()->getPixels(), _system->copyRectToScreen(image._sectionSurfaces[section]->getPixels(),
image._pitch, 0, 0, _screenWidth, _screenHeight); image._pitch, 0, 0, _screenWidth, _screenHeight);
} else { } else {
uint offset = image._section[section].y1 * image._pitch + image._section[section].x1; uint offset = image._section[section].y1 * image._pitch + image._section[section].x1;
_system->copyRectToScreen(static_cast<const byte *>(image.getSurface()->getPixels()) + offset, _system->copyRectToScreen(static_cast<const byte *>(image._sectionSurfaces[section]->getPixels()) + offset,
image._pitch, image._pitch,
sectionRect.top, sectionRect.left, sectionRect.top, sectionRect.left,
sectionRect.width(), sectionRect.height()); sectionRect.width(), sectionRect.height());
@ -309,6 +311,9 @@ void SupernovaEngine::renderImage(MSNImageDecoder &image, int section, bool full
} }
void SupernovaEngine::renderImage(int filenumber, int section, bool fullscreen) { void SupernovaEngine::renderImage(int filenumber, int section, bool fullscreen) {
if (filenumber > ARRAYSIZE(_images) - 1)
return;
renderImage(_images[filenumber], section, fullscreen); renderImage(_images[filenumber], section, fullscreen);
} }