From 148814b2a6c3dffb53b8d902eb7fcfb68110bea3 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Mon, 14 Mar 2016 10:04:51 +0100 Subject: ADL: Move hires1 drawing functions into class --- engines/adl/adl.cpp | 68 +++--------- engines/adl/adl.h | 12 +- engines/adl/graphics.cpp | 231 +-------------------------------------- engines/adl/graphics.h | 27 ++++- engines/adl/graphics_v1.cpp | 120 ++++++++++++++++++++ engines/adl/graphics_v2.cpp | 260 ++++++++++++++++++++++++++++++++++++++++++++ engines/adl/hires1.cpp | 111 +++---------------- engines/adl/hires1.h | 11 +- engines/adl/hires2.cpp | 9 +- engines/adl/hires2.h | 3 +- engines/adl/module.mk | 2 + 11 files changed, 456 insertions(+), 398 deletions(-) create mode 100644 engines/adl/graphics_v1.cpp create mode 100644 engines/adl/graphics_v2.cpp (limited to 'engines/adl') diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp index 47623d45e2..a17339f8ea 100644 --- a/engines/adl/adl.cpp +++ b/engines/adl/adl.cpp @@ -38,16 +38,19 @@ #include "adl/adl.h" #include "adl/display.h" #include "adl/detection.h" +#include "adl/graphics.h" namespace Adl { AdlEngine::~AdlEngine() { delete _display; + delete _graphics; } AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) : Engine(syst), _display(nullptr), + _graphics(nullptr), _gameDescription(gd), _isRestarting(false), _isRestoring(false), @@ -82,6 +85,14 @@ Common::String AdlEngine::readStringAt(Common::SeekableReadStream &stream, uint return readString(stream, until); } +Common::File *AdlEngine::openFile(const Common::String &name) const { + Common::File *f = new Common::File(); + if (!f->open(name)) + error("Error opening '%s'", name.c_str()); + + return f; +} + void AdlEngine::printMessage(uint idx, bool wait) const { Common::String msg = _messages[idx - 1]; wordWrap(msg); @@ -281,10 +292,7 @@ void AdlEngine::drawItems() const { if (item->state == IDI_ITEM_MOVED) { if (getCurRoom().picture == getCurRoom().curPicture) { const Common::Point &p = _itemOffsets[dropped]; - if (item->isLineArt) - drawLineArt(_lineArt[item->picture - 1], p); - else - drawPic(item->picture, p); + drawItem(*item, p); ++dropped; } continue; @@ -294,61 +302,13 @@ void AdlEngine::drawItems() const { for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) { if (*pic == getCurRoom().curPicture) { - if (item->isLineArt) - drawLineArt(_lineArt[item->picture - 1], item->position); - else - drawPic(item->picture, item->position); + drawItem(*item, item->position); continue; } } } } -void AdlEngine::drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant) const { - if (bits & 4) - _display->putPixel(p, color); - - bits += quadrant; - - if (bits & 1) - p.x += (bits & 2 ? -1 : 1); - else - p.y += (bits & 2 ? 1 : -1); -} - -void AdlEngine::drawLineArt(const Common::Array &lineArt, const Common::Point &pos, byte rotation, byte scaling, byte color) const { - const byte stepping[] = { - 0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5, - 0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18, - 0xff - }; - - byte quadrant = rotation >> 4; - rotation &= 0xf; - byte xStep = stepping[rotation]; - byte yStep = stepping[(rotation ^ 0xf) + 1] + 1; - - Common::Point p(pos); - - for (uint i = 0; i < lineArt.size(); ++i) { - byte b = lineArt[i]; - - do { - byte xFrac = 0x80; - byte yFrac = 0x80; - for (uint j = 0; j < scaling; ++j) { - if (xFrac + xStep + 1 > 255) - drawNextPixel(p, color, b, quadrant); - xFrac += xStep + 1; - if (yFrac + yStep > 255) - drawNextPixel(p, color, b, quadrant + 1); - yFrac += yStep; - } - b >>= 3; - } while (b != 0); - } -} - const Room &AdlEngine::getRoom(uint i) const { if (i < 1 || i > _state.rooms.size()) error("Room %i out of range [1, %i]", i, _state.rooms.size()); @@ -447,7 +407,7 @@ void AdlEngine::dropItem(byte noun) { Common::Error AdlEngine::run() { _display = new Display(); - loadData(); + init(); int saveSlot = ConfMan.getInt("save_slot"); if (saveSlot >= 0) { diff --git a/engines/adl/adl.h b/engines/adl/adl.h index d0da3bfec1..d8c631ec48 100644 --- a/engines/adl/adl.h +++ b/engines/adl/adl.h @@ -37,6 +37,7 @@ class SeekableReadStream; namespace Adl { class Display; +class GraphicsMan; struct AdlGameDescription; // Conditional opcodes @@ -142,6 +143,7 @@ protected: Common::String readString(Common::ReadStream &stream, byte until = 0) const; Common::String readStringAt(Common::SeekableReadStream &stream, uint offset, byte until = 0) const; + Common::File *openFile(const Common::String &name) const; virtual void printMessage(uint idx, bool wait = true) const; void delay(uint32 ms) const; @@ -155,8 +157,6 @@ protected: // Graphics void clearScreen() const; void drawItems() const; - void drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant) const; - void drawLineArt(const Common::Array &lineArt, const Common::Point &pos, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const; // Game state functions const Room &getRoom(uint i) const; @@ -175,6 +175,7 @@ protected: void doAllCommands(const Commands &commands, byte verb, byte noun); Display *_display; + GraphicsMan *_graphics; // Message strings in data file Common::Array _messages; @@ -182,9 +183,6 @@ protected: Common::Array _pictures; // Dropped item screen offsets Common::Array _itemOffsets; - // Drawings consisting of horizontal and vertical lines only, but - // supporting scaling and rotation - Common::Array > _lineArt; // lists Commands _roomCommands; Commands _globalCommands; @@ -213,10 +211,10 @@ protected: private: virtual void runIntro() const { } - virtual void loadData() = 0; + virtual void init() = 0; virtual void initState() = 0; virtual void restartGame() = 0; - virtual void drawPic(byte pic, Common::Point pos = Common::Point()) const = 0; + virtual void drawItem(const Item &item, const Common::Point &pos) const = 0; virtual void showRoom() const = 0; // Engine diff --git a/engines/adl/graphics.cpp b/engines/adl/graphics.cpp index 8e8117dafd..f9af442a9f 100644 --- a/engines/adl/graphics.cpp +++ b/engines/adl/graphics.cpp @@ -22,67 +22,14 @@ #include "common/stream.h" #include "common/rect.h" -#include "common/textconsole.h" #include "adl/display.h" #include "adl/graphics.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 Graphics::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const { +void GraphicsMan::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const { int16 deltaX = p2.x - p1.x; int8 xStep = 1; @@ -119,180 +66,4 @@ void Graphics::drawLine(const Common::Point &p1, const Common::Point &p2, byte c } } -void Graphics::clear() { - _display.clear(0xff); - _color = 0; -} - -void Graphics::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 Graphics::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::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 Graphics::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 Graphics::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::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/graphics.h b/engines/adl/graphics.h index 9c47820390..ec29ee073b 100644 --- a/engines/adl/graphics.h +++ b/engines/adl/graphics.h @@ -32,12 +32,32 @@ namespace Adl { class Display; -class Graphics { +class GraphicsMan { public: - Graphics(Display &display) : _display(display) { } + virtual ~GraphicsMan() { } + virtual void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos, byte color) = 0; +protected: + GraphicsMan(Display &display) : _display(display) { } void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const; - void draw(Common::SeekableReadStream &pic); + + Display &_display; +}; + +class Graphics_v1 : public GraphicsMan { +public: + Graphics_v1(Display &display) : GraphicsMan(display) { } + void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos, byte color); + void drawCorners(Common::ReadStream &corners, const Common::Point &pos, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const; + +private: + void drawCornerPixel(Common::Point &p, byte color, byte bits, byte quadrant) const; +}; + +class Graphics_v2 : public GraphicsMan { +public: + Graphics_v2(Display &display) : GraphicsMan(display), _color(0) { } + void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos, byte color); private: void clear(); @@ -47,7 +67,6 @@ private: void fillRow(const Common::Point &p, bool fillBit, byte pattern); void fill(Common::SeekableReadStream &pic); - Display &_display; byte _color; }; diff --git a/engines/adl/graphics_v1.cpp b/engines/adl/graphics_v1.cpp new file mode 100644 index 0000000000..edf16b8be4 --- /dev/null +++ b/engines/adl/graphics_v1.cpp @@ -0,0 +1,120 @@ +/* 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" + +namespace Adl { + +void Graphics_v1::drawPic(Common::SeekableReadStream &pic, const Common::Point &pos, byte color) { + byte x, y; + bool bNewLine = false; + byte oldX = 0, oldY = 0; + while (1) { + x = pic.readByte(); + y = pic.readByte(); + + if (pic.err() || pic.eos()) + error("Error reading picture"); + + if (x == 0xff && y == 0xff) + return; + + if (x == 0 && y == 0) { + bNewLine = true; + continue; + } + + x += pos.x; + y += pos.y; + + if (y > 160) + y = 160; + + if (bNewLine) { + _display.putPixel(Common::Point(x, y), 0x7f); + bNewLine = false; + } else { + drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f); + } + + oldX = x; + oldY = y; + } +} + +void Graphics_v1::drawCornerPixel(Common::Point &p, byte color, byte bits, byte quadrant) const { + if (bits & 4) + _display.putPixel(p, color); + + bits += quadrant; + + if (bits & 1) + p.x += (bits & 2 ? -1 : 1); + else + p.y += (bits & 2 ? 1 : -1); +} + +void Graphics_v1::drawCorners(Common::ReadStream &corners, const Common::Point &pos, byte rotation, byte scaling, byte color) const { + const byte stepping[] = { + 0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5, + 0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18, + 0xff + }; + + byte quadrant = rotation >> 4; + rotation &= 0xf; + byte xStep = stepping[rotation]; + byte yStep = stepping[(rotation ^ 0xf) + 1] + 1; + + Common::Point p(pos); + + while (true) { + byte b = corners.readByte(); + + if (corners.eos() || corners.err()) + error("Error reading corners"); + + if (b == 0) + return; + + do { + byte xFrac = 0x80; + byte yFrac = 0x80; + for (uint j = 0; j < scaling; ++j) { + if (xFrac + xStep + 1 > 255) + drawCornerPixel(p, color, b, quadrant); + xFrac += xStep + 1; + if (yFrac + yStep > 255) + drawCornerPixel(p, color, b, quadrant + 1); + yFrac += yStep; + } + b >>= 3; + } while (b != 0); + } +} + +} // End of namespace Adl diff --git a/engines/adl/graphics_v2.cpp b/engines/adl/graphics_v2.cpp new file mode 100644 index 0000000000..289f43e8de --- /dev/null +++ b/engines/adl/graphics_v2.cpp @@ -0,0 +1,260 @@ +/* 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" + +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 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 <<= 1; \ + READ_BYTE(p.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); + + _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 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.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 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, byte color) { + 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/hires1.cpp b/engines/adl/hires1.cpp index 98e33abbb9..735473864a 100644 --- a/engines/adl/hires1.cpp +++ b/engines/adl/hires1.cpp @@ -136,7 +136,9 @@ void HiRes1Engine::runIntro() const { delay(2000); } -void HiRes1Engine::loadData() { +void HiRes1Engine::init() { + _graphics = new Graphics_v1(*_display); + Common::File f; if (!f.open(IDS_HR1_MESSAGES)) @@ -196,21 +198,10 @@ void HiRes1Engine::loadData() { } // Load right-angle line art - f.seek(IDI_HR1_OFS_LINE_ART); - uint16 lineArtTotal = f.readUint16LE(); - for (uint i = 0; i < lineArtTotal; ++i) { - f.seek(IDI_HR1_OFS_LINE_ART + 2 + i * 2); - uint16 offset = f.readUint16LE(); - f.seek(IDI_HR1_OFS_LINE_ART + offset); - - Common::Array lineArt; - byte b = f.readByte(); - while (b != 0) { - lineArt.push_back(b); - b = f.readByte(); - } - _lineArt.push_back(lineArt); - } + f.seek(IDI_HR1_OFS_CORNERS); + uint16 cornersCount = f.readUint16LE(); + for (uint i = 0; i < cornersCount; ++i) + _corners.push_back(IDI_HR1_OFS_CORNERS + f.readUint16LE()); if (f.eos() || f.err()) error("Failed to read game data from '" IDS_HR1_EXE_1 "'"); @@ -290,7 +281,7 @@ void HiRes1Engine::drawPic(byte pic, Common::Point pos) const { error("Failed to open file '%s'", name.c_str()); f.seek(_pictures[pic].offset); - drawPic(f, pos); + _graphics->drawPic(f, pos, 0x7f); } void HiRes1Engine::printMessage(uint idx, bool wait) const { @@ -312,6 +303,16 @@ void HiRes1Engine::printMessage(uint idx, bool wait) const { AdlEngine::printMessage(idx, wait); } +void HiRes1Engine::drawItem(const Item &item, const Common::Point &pos) const { + if (item.isLineArt) { + Common::File *f = openFile(IDS_HR1_EXE_1); + f->seek(_corners[item.picture - 1]); + static_cast(_graphics)->drawCorners(*f, pos); + delete f; + } else + drawPic(item.picture, pos); +} + void HiRes1Engine::showRoom() const { if (!_state.isDark) { drawPic(getCurRoom().curPicture); @@ -322,82 +323,6 @@ void HiRes1Engine::showRoom() const { printMessage(_roomDesc[_state.room - 1], false); } -void HiRes1Engine::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const { - // This draws a four-connected line - - 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 (1) { - _display->putPixel(p, color); - - if (--steps == 0) - return; - - if (err < 0) { - p.y += yStep; - err += deltaX; - } else { - p.x += xStep; - err += deltaY; - } - } -} - -void HiRes1Engine::drawPic(Common::ReadStream &stream, const Common::Point &pos) const { - byte x, y; - bool bNewLine = false; - byte oldX = 0, oldY = 0; - while (1) { - x = stream.readByte(); - y = stream.readByte(); - - if (stream.err() || stream.eos()) - error("Failed to read picture"); - - if (x == 0xff && y == 0xff) - return; - - if (x == 0 && y == 0) { - bNewLine = true; - continue; - } - - x += pos.x; - y += pos.y; - - if (y > 160) - y = 160; - - if (bNewLine) { - _display->putPixel(Common::Point(x, y), 0x7f); - bNewLine = false; - } else { - drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f); - } - - oldX = x; - oldY = y; - } -} - Engine *HiRes1Engine_create(OSystem *syst, const AdlGameDescription *gd) { return new HiRes1Engine(syst, gd); } diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h index 02cec0137a..96e2fd0122 100644 --- a/engines/adl/hires1.h +++ b/engines/adl/hires1.h @@ -26,6 +26,7 @@ #include "common/str.h" #include "adl/adl.h" +#include "adl/graphics.h" namespace Common { class ReadStream; @@ -82,7 +83,7 @@ namespace Adl { #define IDI_HR1_OFS_CMDS_1 0x3d00 #define IDI_HR1_OFS_ITEM_OFFSETS 0x68ff -#define IDI_HR1_OFS_LINE_ART 0x4f00 +#define IDI_HR1_OFS_CORNERS 0x4f00 #define IDI_HR1_OFS_VERBS 0x3800 #define IDI_HR1_OFS_NOUNS 0x0f00 @@ -94,16 +95,16 @@ public: private: // AdlEngine void runIntro() const; - void loadData(); + void init(); void initState(); void restartGame(); void drawPic(byte pic, Common::Point pos = Common::Point()) const; void printMessage(uint idx, bool wait = true) const; + void drawItem(const Item &item, const Common::Point &pos) const; void showRoom() const; - void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const; - void drawPic(Common::ReadStream &stream, const Common::Point &pos) const; - + Common::File _exe; + Common::Array _corners; Common::Array _roomDesc; }; diff --git a/engines/adl/hires2.cpp b/engines/adl/hires2.cpp index 7bdfde580c..19f447e8be 100644 --- a/engines/adl/hires2.cpp +++ b/engines/adl/hires2.cpp @@ -51,7 +51,9 @@ void HiRes2Engine::runIntro() const { delay(2000); } -void HiRes2Engine::loadData() { +void HiRes2Engine::init() { + _graphics = new Graphics_v2(*_display); + Common::File f; if (!f.open(IDS_HR2_DISK_IMAGE)) @@ -122,8 +124,7 @@ void HiRes2Engine::restartGame() { } void HiRes2Engine::drawPic(byte pic, Common::Point pos) const { - // Temp hack - Graphics test(*_display); + // Temp hack to show a pic Common::File f; @@ -132,7 +133,7 @@ void HiRes2Engine::drawPic(byte pic, Common::Point pos) const { f.seek(0x1000); - test.draw(f); + _graphics->drawPic(f, pos, 0); } void HiRes2Engine::showRoom() const { diff --git a/engines/adl/hires2.h b/engines/adl/hires2.h index 05926ee7b8..f09a62fdcc 100644 --- a/engines/adl/hires2.h +++ b/engines/adl/hires2.h @@ -70,10 +70,11 @@ public: private: // AdlEngine void runIntro() const; - void loadData(); + void init(); void initState(); void restartGame(); void drawPic(byte pic, Common::Point pos) const; + void drawItem(const Item &item, const Common::Point &pos) const { } void showRoom() const; }; diff --git a/engines/adl/module.mk b/engines/adl/module.mk index 6901279262..de4d645dbc 100644 --- a/engines/adl/module.mk +++ b/engines/adl/module.mk @@ -5,6 +5,8 @@ MODULE_OBJS := \ detection.o \ display.o \ graphics.o \ + graphics_v1.o \ + graphics_v2.o \ hires1.o \ hires2.o -- cgit v1.2.3