diff options
| -rw-r--r-- | engines/adl/adl.cpp | 68 | ||||
| -rw-r--r-- | engines/adl/adl.h | 12 | ||||
| -rw-r--r-- | engines/adl/graphics.cpp | 231 | ||||
| -rw-r--r-- | engines/adl/graphics.h | 27 | ||||
| -rw-r--r-- | engines/adl/graphics_v1.cpp | 120 | ||||
| -rw-r--r-- | engines/adl/graphics_v2.cpp | 260 | ||||
| -rw-r--r-- | engines/adl/hires1.cpp | 111 | ||||
| -rw-r--r-- | engines/adl/hires1.h | 11 | ||||
| -rw-r--r-- | engines/adl/hires2.cpp | 9 | ||||
| -rw-r--r-- | engines/adl/hires2.h | 3 | ||||
| -rw-r--r-- | engines/adl/module.mk | 2 | 
11 files changed, 456 insertions, 398 deletions
| 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<byte> &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<byte> &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<Common::String> _messages; @@ -182,9 +183,6 @@ protected:  	Common::Array<Picture> _pictures;  	// Dropped item screen offsets  	Common::Array<Common::Point> _itemOffsets; -	// Drawings consisting of horizontal and vertical lines only, but -	// supporting scaling and rotation -	Common::Array<Common::Array<byte> > _lineArt;  	// <room, verb, noun, script> 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<byte> 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_v1 *>(_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<uint> _corners;  	Common::Array<byte> _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 | 
