diff options
Diffstat (limited to 'engines/adl/graphics_v2.cpp')
-rw-r--r-- | engines/adl/graphics_v2.cpp | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/engines/adl/graphics_v2.cpp b/engines/adl/graphics_v2.cpp new file mode 100644 index 0000000000..40936f5b7d --- /dev/null +++ b/engines/adl/graphics_v2.cpp @@ -0,0 +1,304 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/stream.h" +#include "common/rect.h" +#include "common/textconsole.h" + +#include "adl/display.h" +#include "adl/graphics.h" +#include "adl/adl.h" + +namespace Adl { + +// FIXME: Add clipping + +#define NUM_PATTERNS 22 +#define PATTERN_LEN 4 +static const byte fillPatterns[NUM_PATTERNS][PATTERN_LEN] = { + { 0x00, 0x00, 0x00, 0x00 }, + { 0x80, 0x80, 0x80, 0x80 }, + { 0xff, 0xff, 0xff, 0xff }, + { 0x7f, 0x7f, 0x7f, 0x7f }, + { 0x2a, 0x55, 0x2a, 0x55 }, + { 0xaa, 0xd5, 0xaa, 0xd5 }, + { 0x55, 0x2a, 0x55, 0x2a }, + { 0xd5, 0xaa, 0xd5, 0xaa }, + { 0x33, 0x66, 0x4c, 0x19 }, + { 0xb3, 0xe6, 0xcc, 0x99 }, + { 0x22, 0x44, 0x08, 0x11 }, + { 0xa2, 0xc4, 0x88, 0x91 }, + { 0x11, 0x22, 0x44, 0x08 }, + { 0x91, 0xa2, 0xc4, 0x88 }, + { 0x6e, 0x5d, 0x3b, 0x77 }, + { 0xee, 0xdd, 0xbb, 0xf7 }, + { 0x5d, 0x3b, 0x77, 0x6e }, + { 0xdd, 0xbb, 0xf7, 0xee }, + { 0x66, 0x4c, 0x19, 0x33 }, + { 0xe6, 0xcc, 0x99, 0xb3 }, + { 0x33, 0x66, 0x4c, 0x19 }, + { 0xb3, 0xe6, 0xcc, 0x99 } +}; + +#define MIN_COMMAND 0xe0 + +#define CHECK_COMMAND(X) \ + do { \ + if ((X) >= MIN_COMMAND) { \ + pic.seek(-1, SEEK_CUR); \ + return; \ + } \ + } while (0) + +#define READ_BYTE(b) \ + do { \ + b = pic.readByte(); \ + if (pic.eos() || pic.err()) \ + error("Error reading picture"); \ + CHECK_COMMAND(b); \ + } while (0) + +#define READ_POINT(p) \ + do { \ + READ_BYTE(p.x); \ + p.x += _offset.x; \ + p.x <<= 1; \ + READ_BYTE(p.y); \ + p.y += _offset.y; \ + } while (0) + +void Graphics_v2::clear() { + _display.clear(0xff); + _color = 0; +} + +void Graphics_v2::drawCorners(Common::SeekableReadStream &pic, bool yFirst) { + Common::Point p; + + READ_POINT(p); + + if (yFirst) + goto doYStep; + + while (true) { + int16 n; + + READ_BYTE(n); + n += _offset.x; + + _display.putPixel(p, _color); + + n <<= 1; + drawLine(p, Common::Point(n, p.y), _color); + p.x = n; + +doYStep: + READ_BYTE(n); + n += _offset.y; + + _display.putPixel(p, _color); + drawLine(p, Common::Point(p.x, n), _color); + + _display.putPixel(Common::Point(p.x + 1, p.y), _color); + drawLine(Common::Point(p.x + 1, p.y), Common::Point(p.x + 1, n), _color); + + p.y = n; + } +} + +void Graphics_v2::drawRelativeLines(Common::SeekableReadStream &pic) { + Common::Point p1; + + READ_POINT(p1); + _display.putPixel(p1, _color); + + while (true) { + Common::Point p2(p1); + + byte n; + READ_BYTE(n); + + byte h = (n & 0x70) >> 4; + byte l = n & 7; + + if (n & 0x80) + p2.x -= (h << 1); + else + p2.x += (h << 1); + + if (n & 8) + p2.y -= l; + else + p2.y += l; + + drawLine(p1, p2, _color); + p1 = p2; + } +} + +void Graphics_v2::drawAbsoluteLines(Common::SeekableReadStream &pic) { + Common::Point p1; + + READ_POINT(p1); + _display.putPixel(p1, _color); + + while (true) { + Common::Point p2; + + READ_POINT(p2); + drawLine(p1, p2, _color); + p1 = p2; + } +} + +static byte getPatternColor(const Common::Point &p, byte pattern) { + if (pattern >= NUM_PATTERNS) + error("Invalid fill pattern %i encountered in picture", pattern); + + byte offset = (p.y & 1) << 1; + offset += (p.x / 7) & 3; + + return fillPatterns[pattern][offset % PATTERN_LEN]; +} + +void Graphics_v2::fillRow(const Common::Point &p, bool stopBit, byte pattern) { + const byte color = getPatternColor(p, pattern); + _display.setPixelPalette(p, color); + _display.setPixelBit(p, color); + + Common::Point q(p); + byte c = color; + + while (++q.x < DISPLAY_WIDTH) { + if ((q.x % 7) == 0) { + c = getPatternColor(q, pattern); + // Palette is set before the first bit is tested + _display.setPixelPalette(q, c); + } + if (_display.getPixelBit(q) == stopBit) + break; + _display.setPixelBit(q, c); + } + + q = p; + c = color; + while (--q.x >= 0) { + if ((q.x % 7) == 6) { + c = getPatternColor(q, pattern); + _display.setPixelPalette(q, c); + } + if (_display.getPixelBit(q) == stopBit) + break; + _display.setPixelBit(q, c); + } +} + +// Basic flood fill +void Graphics_v2::fill(Common::SeekableReadStream &pic) { + byte pattern; + READ_BYTE(pattern); + + while (true) { + Common::Point p; + READ_POINT(p); + + bool stopBit = !_display.getPixelBit(p); + + while (--p.y >= 0) { + if (_display.getPixelBit(p) == stopBit) + break; + if (_display.getPixelBit(Common::Point(p.x + 1, p.y)) == stopBit) + break; + } + + while (++p.y < DISPLAY_HEIGHT) { + if (_display.getPixelBit(p) == stopBit) + break; + if (_display.getPixelBit(Common::Point(p.x + 1, p.y)) == stopBit) + break; + fillRow(p, stopBit, pattern); + } + } +} + +void Graphics_v2::drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) { + _color = 0; + _offset = pos; + + while (true) { + byte opcode = pic.readByte(); + + if (pic.eos() || pic.err()) + error("Error reading picture"); + + switch (opcode) { + case 0xe0: + drawCorners(pic, false); + break; + case 0xe1: + drawCorners(pic, true); + break; + case 0xe2: + drawRelativeLines(pic); + break; + case 0xe3: + drawAbsoluteLines(pic); + break; + case 0xe4: + fill(pic); + break; + case 0xe5: + clear(); + break; + case 0xf0: + _color = 0x00; + break; + case 0xf1: + _color = 0x2a; + break; + case 0xf2: + _color = 0x55; + break; + case 0xf3: + _color = 0x7f; + break; + case 0xf4: + _color = 0x80; + break; + case 0xf5: + _color = 0xaa; + break; + case 0xf6: + _color = 0xd5; + break; + case 0xf7: + _color = 0xff; + break; + case 0xff: + return; + default: + error("Invalid pic opcode %02x", opcode); + } + } +} + +} // End of namespace Adl |