diff options
| author | Walter van Niftrik | 2016-03-11 23:46:41 +0100 |
|---|---|---|
| committer | Walter van Niftrik | 2016-06-06 20:35:49 +0200 |
| commit | 930bdcfa9101e37b984072102a8b8ef0a25afbf6 (patch) | |
| tree | 504919ab1ecc63b45305355d898754fbe9c7b6da | |
| parent | 641d87f7524781dd1fc7e014e7c8f5bf361eca09 (diff) | |
| download | scummvm-rg350-930bdcfa9101e37b984072102a8b8ef0a25afbf6.tar.gz scummvm-rg350-930bdcfa9101e37b984072102a8b8ef0a25afbf6.tar.bz2 scummvm-rg350-930bdcfa9101e37b984072102a8b8ef0a25afbf6.zip | |
ADL: Implement hires2 PIC drawing
| -rw-r--r-- | engines/adl/display.cpp | 22 | ||||
| -rw-r--r-- | engines/adl/display.h | 2 | ||||
| -rw-r--r-- | engines/adl/hires2.cpp | 14 | ||||
| -rw-r--r-- | engines/adl/module.mk | 3 | ||||
| -rw-r--r-- | engines/adl/picture.cpp | 298 | ||||
| -rw-r--r-- | engines/adl/picture.h | 56 |
6 files changed, 393 insertions, 2 deletions
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 6342504bc3..37959735fd 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -219,9 +219,24 @@ void Display::loadFrameBuffer(Common::ReadStream &stream) { error("Failed to read frame buffer"); } +void Display::putPixelRaw(const Common::Point &p, byte color) { + byte *b = _frameBuf + p.y * DISPLAY_PITCH + (p.x / 7); + color ^= *b; + color &= 0x80 | (1 << (p.x % 7)); + *b ^= color; +} + void Display::putPixel(const Common::Point &p, byte color) { byte offset = p.x / 7; + byte mask = 0x80 | (1 << (p.x % 7)); + // Since white and black are in both palettes, we leave + // the palette bit alone + if ((color & 0x7f) == 0x7f || (color & 0x7f) == 0) + mask &= 0x7f; + + // Adjust colors starting with bits '01' or '10' for + // odd offsets if (offset & 1) { byte c = color << 1; if (c >= 0x40 && c < 0xc0) @@ -230,10 +245,15 @@ void Display::putPixel(const Common::Point &p, byte color) { byte *b = _frameBuf + p.y * DISPLAY_PITCH + offset; color ^= *b; - color &= 1 << (p.x % 7); + color &= mask; *b ^= color; } +bool Display::getPixelBit(const Common::Point &p) const { + byte *b = _frameBuf + p.y * DISPLAY_PITCH + (p.x / 7); + return *b & (1 << (p.x % 7)); +} + void Display::clear(byte color) { byte val = 0; diff --git a/engines/adl/display.h b/engines/adl/display.h index ff01e3faf2..67d8bf4392 100644 --- a/engines/adl/display.h +++ b/engines/adl/display.h @@ -61,7 +61,9 @@ public: // Graphics void loadFrameBuffer(Common::ReadStream &stream); + void putPixelRaw(const Common::Point &p, byte color); void putPixel(const Common::Point &p, byte color); + bool getPixelBit(const Common::Point &p) const; void clear(byte color); // Text diff --git a/engines/adl/hires2.cpp b/engines/adl/hires2.cpp index 1c4377180d..c36e151969 100644 --- a/engines/adl/hires2.cpp +++ b/engines/adl/hires2.cpp @@ -28,6 +28,7 @@ #include "adl/hires2.h" #include "adl/display.h" +#include "adl/picture.h" namespace Adl { @@ -121,9 +122,22 @@ void HiRes2Engine::restartGame() { } void HiRes2Engine::drawPic(byte pic, Common::Point pos) const { + // Temp hack + PictureD test(*_display); + + Common::File f; + + if (!f.open(IDS_HR2_DISK_IMAGE)) + error("Failed to open file '" IDS_HR2_DISK_IMAGE "'"); + + f.seek(0x1000); + + test.draw(f); } void HiRes2Engine::showRoom() const { + drawPic(0, Common::Point()); + _display->updateHiResScreen(); } Engine *HiRes2Engine_create(OSystem *syst, const AdlGameDescription *gd) { diff --git a/engines/adl/module.mk b/engines/adl/module.mk index de69b52621..8162e51665 100644 --- a/engines/adl/module.mk +++ b/engines/adl/module.mk @@ -5,7 +5,8 @@ MODULE_OBJS := \ detection.o \ display.o \ hires1.o \ - hires2.o + hires2.o \ + picture.o MODULE_DIRS += \ engines/adl diff --git a/engines/adl/picture.cpp b/engines/adl/picture.cpp new file mode 100644 index 0000000000..567165af62 --- /dev/null +++ b/engines/adl/picture.cpp @@ -0,0 +1,298 @@ +/* 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/picture.h" + +#define MIN_COMMAND 0xe0 + +namespace Adl { + +#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 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()) \ + return; \ + CHECK_COMMAND(b); \ + } while (0) + +#define READ_POINT(p) \ + do { \ + READ_BYTE(p.x); \ + p.x <<= 1; \ + READ_BYTE(p.y); \ + } while (0) + +// Draws a four-connected line +void PictureD::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const { + int16 deltaX = p2.x - p1.x; + int8 xStep = 1; + + if (deltaX < 0) { + deltaX = -deltaX; + xStep = -1; + } + + int16 deltaY = p2.y - p1.y; + int8 yStep = -1; + + if (deltaY > 0) { + deltaY = -deltaY; + yStep = 1; + } + + Common::Point p(p1); + int16 steps = deltaX - deltaY + 1; + int16 err = deltaX + deltaY; + + while (true) { + _display.putPixel(p, color); + + if (--steps == 0) + return; + + if (err < 0) { + p.y += yStep; + err += deltaX; + } else { + p.x += xStep; + err += deltaY; + } + } +} + +void PictureD::clear() { + _display.clear(0xff); + _color = 0; +} + +void PictureD::drawCorners(Common::SeekableReadStream &pic, bool yFirst) { + Common::Point p; + + READ_POINT(p); + + if (yFirst) + goto doYStep; + + while (true) { + int16 n; + + READ_BYTE(n); + + _display.putPixel(p, _color); + + n <<= 1; + drawLine(p, Common::Point(n, p.y), _color); + p.x = n; + +doYStep: + READ_BYTE(n); + + _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 PictureD::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 PictureD::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", pattern); + + byte offset = (p.y & 1) << 1; + offset += (p.x / 7) & 3; + + return fillPatterns[pattern][offset % PATTERN_LEN]; +} + +void PictureD::fillRow(const Common::Point &p, bool stopBit, byte pattern) { + const byte color = getPatternColor(p, pattern); + _display.putPixelRaw(p, color); + + Common::Point q(p); + byte c = color; + + while (++q.x < DISPLAY_WIDTH && _display.getPixelBit(q) != stopBit) { + if ((q.x % 7) == 0) + c = getPatternColor(q, pattern); + _display.putPixelRaw(q, c); + } + + q = p; + c = color; + while (--q.x >= 0 && _display.getPixelBit(q) != stopBit) { + if ((q.x % 7) == 6) + c = getPatternColor(q, pattern); + _display.putPixelRaw(q, c); + } +} + +// Basic flood fill +void PictureD::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 PictureD::draw(Common::SeekableReadStream &pic) { + 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 0xff: + return; + default: + error("Invalid pic opcode %02x", opcode); + } + } +} + +} // End of namespace Adl diff --git a/engines/adl/picture.h b/engines/adl/picture.h new file mode 100644 index 0000000000..990c8561d9 --- /dev/null +++ b/engines/adl/picture.h @@ -0,0 +1,56 @@ +/* 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. + * + */ + +#ifndef ADL_PICTURE_H +#define ADL_PICTURE_H + +namespace Common{ +class SeekableReadStream; +class Point; +} + +namespace Adl { + +class Display; + +class PictureD { +public: + PictureD(Display &display) : _display(display) { } + + void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const; + void draw(Common::SeekableReadStream &pic); + +private: + void clear(); + void drawCorners(Common::SeekableReadStream &pic, bool yFirst); + void drawRelativeLines(Common::SeekableReadStream &pic); + void drawAbsoluteLines(Common::SeekableReadStream &pic); + void fillRow(const Common::Point &p, bool fillBit, byte pattern); + void fill(Common::SeekableReadStream &pic); + + Display &_display; + byte _color; +}; + +} // End of namespace Adl + +#endif |
