aboutsummaryrefslogtreecommitdiff
path: root/engines/supernova/graphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/supernova/graphics.cpp')
-rw-r--r--engines/supernova/graphics.cpp157
1 files changed, 154 insertions, 3 deletions
diff --git a/engines/supernova/graphics.cpp b/engines/supernova/graphics.cpp
index 1daa94b42d..e2467d1c3c 100644
--- a/engines/supernova/graphics.cpp
+++ b/engines/supernova/graphics.cpp
@@ -1,11 +1,162 @@
+#include "common/algorithm.h"
+#include "common/file.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "graphics/palette.h"
+#include "graphics/surface.h"
+
#include "graphics.h"
+namespace Supernova {
+
MSNImageDecoder::MSNImageDecoder()
-{
+ : _surface(NULL)
+ , _palette(NULL) {
+}
+MSNImageDecoder::~MSNImageDecoder() {
+ destroy();
}
-MSNImageDecoder::~MSNImageDecoder()
-{
+bool MSNImageDecoder::loadStream(Common::SeekableReadStream &stream) {
+ destroy();
+
+ size_t size = 0;
+ size = (stream.readUint16LE() + 0xF) >> 4;
+ size |= (stream.readUint16LE() & 0xF) << 12;
+ size += 0x70; // zus_paragraph
+ size *= 16; // a paragraph is 16 bytes
+ _encodedImage = new byte[size];
+
+ _palette = new byte[768];
+ g_system->getPaletteManager()->grabPalette(_palette, 0, 256);
+
+ byte pal_diff;
+ byte flag = stream.readByte();
+ if (flag == 0) {
+ pal_diff = 0;
+ _palette[141] = 0x38;
+ _palette[142] = 0x38;
+ _palette[143] = 0x38;
+ } else {
+ pal_diff = 1;
+ for (int i = flag * 3; i != 0; --i) {
+ _palette[717 - i] = stream.readByte();
+ }
+ }
+ g_system->getPaletteManager()->setPalette(_palette, 0, 256);
+
+ byte numSections = stream.readByte();
+ for (size_t i = 0; i < kMaxSections; ++i) {
+ _section[i].addressHigh = 0xff;
+ _section[i].addressLow = 0xffff;
+ _section[i].x2 = 0;
+ }
+ for (int i = 0; i < numSections; ++i) {
+ _section[i].x1 = stream.readUint16LE();
+ _section[i].x2 = stream.readUint16LE();
+ _section[i].y1 = stream.readByte();
+ _section[i].y2 = stream.readByte();
+ _section[i].next = stream.readByte();
+ _section[i].addressLow = stream.readUint16LE();
+ _section[i].addressHigh = stream.readByte();
+ }
+
+ byte numClickFields = stream.readByte();
+ for (int i = 0; i < numClickFields; ++i) {
+ _clickField[i].x1 = stream.readUint16LE();
+ _clickField[i].x2 = stream.readUint16LE();
+ _clickField[i].y1 = stream.readByte();
+ _clickField[i].y2 = stream.readByte();
+ _clickField[i].next = stream.readByte();
+ }
+
+ byte zwCodes[256];
+ byte numRepeat = stream.readByte();
+ byte numZw = stream.readByte();
+ stream.read(zwCodes, numZw);
+ numZw += numRepeat;
+
+ byte input = 0;
+ size_t i = 0;
+ // wat
+ while (stream.read(&input, 1)) {
+ if (input < numRepeat) {
+ ++input;
+ byte value = stream.readByte();
+ for (--value; input > 0; --input) {
+ _encodedImage[i++] = value;
+ }
+ } else if (input < numZw) {
+ input = zwCodes[input];
+ --input;
+ _encodedImage[i++] = input;
+ _encodedImage[i++] = input;
+ } else {
+ input -= pal_diff;
+ _encodedImage[i++] = input;
+ }
+ }
+ return true;
+}
+
+bool MSNImageDecoder::loadSection(int section) {
+ _surface = new Graphics::Surface;
+ _surface->create(320, 200, g_system->getScreenFormat());
+ byte *surfacePixels = static_cast<byte *>(_surface->getPixels());
+
+ const uint32 kInvalidAddress = 0x00FFFFFF;
+
+ size_t image = section;
+ if (image < 128) {
+ do {
+ uint32 offset = (_section[image].addressHigh << 16) + _section[image].addressLow;
+ if (offset == kInvalidAddress) {
+ return false;
+ }
+ int width = _section[image].x2 - _section[image].x1 + 1;
+ int height = _section[image].y2 - _section[image].y1 + 1;
+ uint32 destAddress = 320 * _section[image].y1 + _section[image].x1;
+ while (height) {
+ Common::copy(_encodedImage + offset, _encodedImage + offset + width, surfacePixels + destAddress);
+ offset += width;
+ destAddress += 320;
+ --height;
+ }
+
+ image = _section[image].next;
+ } 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 = 320 * _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 += 320;
+ destAddress += 320;
+ --height;
+ }
+
+ image = _section[image].next;
+ } while (image != 0);
+ }
+
+ return true;
+}
+
+void MSNImageDecoder::destroy() {
+ if (_palette) {
+ delete[] _palette;
+ _palette = NULL;
+ }
+ if (_surface) {
+ _surface->free();
+ _surface = NULL;
+ }
+}
+
}