diff options
| -rw-r--r-- | engines/mads/font.cpp | 160 | ||||
| -rw-r--r-- | engines/mads/font.h | 31 | ||||
| -rw-r--r-- | engines/mads/mads.cpp | 4 | ||||
| -rw-r--r-- | engines/mads/nebular/dialogs_nebular.cpp | 167 | ||||
| -rw-r--r-- | engines/mads/nebular/dialogs_nebular.h | 75 | ||||
| -rw-r--r-- | engines/mads/palette.cpp | 43 | ||||
| -rw-r--r-- | engines/mads/palette.h | 42 | 
7 files changed, 330 insertions, 192 deletions
| diff --git a/engines/mads/font.cpp b/engines/mads/font.cpp index 076eca92c6..52541500c9 100644 --- a/engines/mads/font.cpp +++ b/engines/mads/font.cpp @@ -28,14 +28,6 @@  namespace MADS { -Font *Font::init(MADSEngine *vm) { -	if (vm->getGameFeatures() & GF_MADS) { -		return new FontMADS(vm); -	} else { -		return new FontM4(vm); -	} -} -  Font::Font(MADSEngine *vm) : _vm(vm) {  	_sysFont = true; @@ -53,6 +45,43 @@ Font::~Font() {  	}  } +void Font::setFont(const Common::String &filename) { +	if (!_filename.empty() && (filename == _filename)) +		// Already using specified font, so don't bother reloading +		return; + +	_sysFont = false; +	_filename = filename; + +	MadsPack fontData(filename, _vm); +	Common::SeekableReadStream *fontFile = fontData.getItemStream(0); + +	_maxHeight = fontFile->readByte(); +	_maxWidth = fontFile->readByte(); + +	_charWidths = new uint8[128]; +	// Char data is shifted by 1 +	_charWidths[0] = 0; +	fontFile->read(_charWidths + 1, 127); +	fontFile->readByte();	// remainder + +	_charOffs = new uint16[128]; + +	uint startOffs = 2 + 128 + 256; +	uint fontSize = fontFile->size() - startOffs; + +	// Char data is shifted by 1 +	_charOffs[0] = 0; +	for (int i = 1; i < 128; i++) +		_charOffs[i] = fontFile->readUint16LE() - startOffs; +	fontFile->readUint16LE();	// remainder + +	_charData = new uint8[fontSize]; +	fontFile->read(_charData, fontSize); + +	delete fontFile; +} +  void Font::setColor(uint8 color) {  	if (_sysFont)  		_fontColors[1] = color; @@ -60,14 +89,11 @@ void Font::setColor(uint8 color) {  		_fontColors[3] = color;		  } -void Font::setColors(uint8 alt1, uint8 alt2, uint8 foreground) { -	if (_sysFont) -		_fontColors[1] = foreground; -	else { -		_fontColors[1] = alt1; -		_fontColors[2] = alt2; -		_fontColors[3] = foreground; -	} +void Font::setColors(uint8 v1, uint8 v2, uint8 v3, uint8 v4) { +	_fontColors[0] = v1; +	_fontColors[1] = v2; +	_fontColors[2] = v3; +	_fontColors[3] = v4;  }  int Font::write(MSurface *surface, const Common::String &msg, const Common::Point &pt, int width, int spaceWidth, uint8 colors[]) { @@ -160,11 +186,6 @@ int Font::write(MSurface *surface, const Common::String &msg, const Common::Poin  }  int Font::getWidth(const Common::String &msg, int spaceWidth) { -	/* -	if (custom_ascii_converter) {			 // if there is a function to convert the extended ASCII characters -		custom_ascii_converter(out_string);	 // call it with the string -	} -	*/  	int width = 0;  	const char *text = msg.c_str(); @@ -173,46 +194,7 @@ int Font::getWidth(const Common::String &msg, int spaceWidth) {  	return width;  } -/*------------------------------------------------------------------------*/ - -void FontMADS::setFont(const Common::String &filename) { -	if (!_filename.empty() && (filename == _filename)) -		// Already using specified font, so don't bother reloading -		return; - -	_sysFont = false; -	_filename = filename; - -	MadsPack fontData(filename, _vm); -	Common::SeekableReadStream *fontFile = fontData.getItemStream(0); - -	_maxHeight = fontFile->readByte(); -	_maxWidth = fontFile->readByte(); - -	_charWidths = new uint8[128]; -	// Char data is shifted by 1 -	_charWidths[0] = 0; -	fontFile->read(_charWidths + 1, 127); -	fontFile->readByte();	// remainder - -	_charOffs = new uint16[128]; - -	uint startOffs = 2 + 128 + 256; -	uint fontSize = fontFile->size() - startOffs; - -	// Char data is shifted by 1 -	_charOffs[0] = 0; -	for (int i = 1; i < 128; i++) -		_charOffs[i] = fontFile->readUint16LE() - startOffs; -	fontFile->readUint16LE();	// remainder - -	_charData = new uint8[fontSize]; -	fontFile->read(_charData, fontSize); - -	delete fontFile; -} - -int FontMADS::getBpp(int charWidth) { +int Font::getBpp(int charWidth) {  	if (charWidth > 12)  		return 4;  	else if (charWidth > 8) @@ -223,60 +205,4 @@ int FontMADS::getBpp(int charWidth) {  		return 1;  } -/*------------------------------------------------------------------------*/ - -void FontM4::setFont(const Common::String &filename) { -	if (!_filename.empty() && (filename == _filename)) -		// Already using specified font, so don't bother reloading -		return; - -	_sysFont = false; -	_filename = filename; - -	Common::SeekableReadStream *fontFile = nullptr; //_vm->_resources->openFile(filename); -	 -	if (fontFile->readUint32LE() != MKTAG('F', 'O', 'N', 'T')) { -		warning("Font: FONT tag expected"); -		return; -	} - -	_maxHeight = fontFile->readByte(); -	_maxWidth = fontFile->readByte(); -	uint fontSize = fontFile->readUint32LE(); -	 -	//printf("Font::Font: _maxWidth = %d, _maxHeight = %d, fontSize = %d\n", _maxWidth, _maxHeight, fontSize); - -	if (fontFile->readUint32LE() != MKTAG('W', 'I', 'D', 'T')) { -		warning("Font: WIDT tag expected"); -		return; -	} - -	_charWidths = new uint8[256]; -	fontFile->read(_charWidths, 256); - -	if (fontFile->readUint32LE() != MKTAG('O', 'F', 'F', 'S')) { -		warning("Font: OFFS tag expected\n"); -		return; -	} - -	_charOffs = new uint16[256]; - -	for (int i = 0; i < 256; i++) -		_charOffs[i] = fontFile->readUint16LE(); - -	if (fontFile->readUint32LE() != MKTAG('P', 'I', 'X', 'S')) { -		warning("Font: PIXS tag expected\n"); -		return; -	} - -	_charData = new uint8[fontSize]; -	fontFile->read(_charData, fontSize); - -//	_vm->_resources->toss(filename); -} - -int FontM4::getBpp(int charWidth) { -	return charWidth / 4 + 1; -} -  } // End of namespace MADS diff --git a/engines/mads/font.h b/engines/mads/font.h index d36be80830..3f01260fbd 100644 --- a/engines/mads/font.h +++ b/engines/mads/font.h @@ -62,19 +62,16 @@ protected:  	Common::String _filename;  	uint8 _fontColors[4]; -protected: -	Font(MADSEngine *vm); - -	virtual void setFont(const Common::String &filename) = 0; -	virtual int getBpp(int charWidth) = 0; -public: -	static Font *init(MADSEngine *vm); +	int getBpp(int charWidth);  public: +	Font(MADSEngine *vm);  	virtual ~Font(); +	void setFont(const Common::String &filename);  	void setColor(uint8 color); -	void setColors(uint8 alt1, uint8 alt2, uint8 foreground); +	void setColors(uint8 v1, uint8 v2, uint8 v3, uint8 v4); +	int maxWidth() const { return _maxWidth; }  	int getWidth(const Common::String &msg, int spaceWidth = -1);  	int getHeight() const { return _maxHeight; }  	int write(MSurface *surface, const Common::String &msg, const Common::Point &pt, int width, int spaceWidth, uint8 colors[]); @@ -83,24 +80,6 @@ public:  	}  }; -class FontMADS: public Font { -	friend class Font; -protected: -	virtual void setFont(const Common::String &filename); -	virtual int getBpp(int charWidth); - -	FontMADS(MADSEngine *vm): Font(vm) {} -}; - -class FontM4: public Font { -	friend class Font; -protected: -	virtual void setFont(const Common::String &filename); -	virtual int getBpp(int charWidth); - -	FontM4(MADSEngine *vm): Font(vm) {} -}; -  } // End of namespace MADS  #endif /* MADS_FONT_H */ diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index ec99b314a7..827c62ac61 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -74,8 +74,8 @@ void MADSEngine::initialise() {  	ResourcesManager::init(this);  	_events = new EventsManager(this); -	_palette = Palette::init(this); -	_font = Font::init(this); +	_palette = new Palette(this); +	_font = new Font(this);  	_screen = MSurface::init(true);  	_sound = new SoundManager(this, _mixer);  	_userInterface = UserInterface::init(this); diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index cd7ab86590..85b06ce592 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -31,15 +31,178 @@ namespace MADS {  namespace Nebular { +TextDialog::TextDialog(MADSEngine *vm, const Common::String &fontName,  +		const Common::Point &pos, int maxChars) { +	_vm = vm; +	_fontName = fontName; +	_position = pos; +	 +	_vm->_font->setFont(FONT_INTERFACE); +	_vm->_font->setColors(TEXTDIALOG_FONT, TEXTDIALOG_FONT, TEXTDIALOG_FONT, TEXTDIALOG_FONT); + +	_innerWidth = (_vm->_font->maxWidth() + 1) * maxChars; +	_width = _innerWidth + 10; +	_lineSize = maxChars * 2; +	_lineWidth = 0; +	_currentX = 0; +	_numLines = 0; +	Common::fill(&_lineXp[0], &_lineXp[TEXT_DIALOG_MAX_LINES], 0); +	 +	Common::copy(&_vm->_palette->_mainPalette[TEXTDIALOG_F8 * 3],  +		&_vm->_palette->_mainPalette[TEXTDIALOG_F8 * 3 + 8 * 3],  +		&_savedPalette[0]); +	Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_F8, 2, 0x24, 0x20); +	Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FA, 2, 0x27, 0x1C); +	Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FC, 2, 0x24, 0x20); +	Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FE, 1, 0x37, 0x37); + +	_vm->_palette->setPalette(_vm->_palette->_mainPalette + (TEXTDIALOG_F8 * 3), +		TEXTDIALOG_F8, 8); +} + +TextDialog::~TextDialog() { +} + +void TextDialog::addLine(const Common::String &line, bool underline) { +	if (_lineWidth > 0 || _currentX > 0) +		incNumLines(); + +	int stringWidth = _vm->_font->getWidth(line); +	if (stringWidth >= _innerWidth || (int)line.size() >= _lineSize) { +		wordWrap(line); +	} else { +		_lineXp[_numLines] = (_innerWidth / 2) - (stringWidth / 2); +		_lines[_numLines] = line; + +		if (underline) +			underlineLine(); +	} + +	incNumLines(); +} + +void TextDialog::underlineLine() { +	_lineXp[_numLines] |= 0x80; +} + +void TextDialog::incNumLines() { +	_lineWidth = 0; +	_currentX = 0; +	if (++_numLines == TEXT_DIALOG_MAX_LINES) +		error("Exceeded text dialog line max"); +} + +void TextDialog::wordWrap(const Common::String &line) { +	Common::String tempLine; + +	if (!line.empty()) { +		const char *srcP = line.c_str(); +		 +		do { +			tempLine = ""; +			bool endWord = false; +			bool newLine = false; +			bool continueFlag = true; + +			do { +				if (!*srcP) { +					continueFlag = false; +				} else { +					tempLine += *srcP; + +					if (*srcP == 10) { +						continueFlag = false; +						newLine = true; +						++srcP; +						tempLine.deleteLastChar(); +					} else if (*srcP == ' ') { +						++srcP; +						endWord = true; +					} else if (!endWord) { +						++srcP; +					} else { +						tempLine.deleteLastChar(); +						continueFlag = false; +					} +				} +			} while (continueFlag); + +			if (tempLine.hasSuffix(" ")) +				tempLine.deleteLastChar(); + +			Common::String tempLine2; +			if (_currentX > 0) +				tempLine2 += ' '; +			tempLine2 += tempLine; + +			int lineWidth = _vm->_font->getWidth(tempLine2, 1); +			if (((_currentX + (int)tempLine2.size()) > _lineSize) || +					((_lineWidth + lineWidth) > _innerWidth)) { +				incNumLines(); +				appendLine(tempLine); +			} else { +				appendLine(tempLine2); +			} + +			if (newLine) +				incNumLines(); +		} while (*srcP); +	} +} + +void TextDialog::appendLine(const Common::String &line) { +	_currentX += line.size(); +	_lineWidth += _vm->_font->getWidth(line, 1); +	_lines[_numLines] += line; +} + +/*------------------------------------------------------------------------*/ +  bool CopyProtectionDialog::show(MADSEngine *vm) { -	CopyProtectionDialog *dlg = new CopyProtectionDialog(vm); +	CopyProtectionDialog *dlg = new CopyProtectionDialog(vm, false);  	delete dlg;  	return true;  } -CopyProtectionDialog::CopyProtectionDialog(MADSEngine *vm): _vm(vm) { +CopyProtectionDialog::CopyProtectionDialog(MADSEngine *vm, bool priorAnswerWrong): +		TextDialog(vm, FONT_INTERFACE_MADS, Common::Point(-1, -1), 32) {  	getHogAnusEntry(_hogEntry); + +	if (priorAnswerWrong) { +		addLine("ANSWER INCORRECT!", true); +		wordWrap("\n"); +		addLine("(But we'll give you another chance!)"); +	} else { +		addLine("REX NEBULAR version 8.43", true); +		wordWrap("\n"); +		addLine("(Copy Protection, for your convenience)"); +	} +	wordWrap("\n"); + +	wordWrap("Now comes the part that everybody hates.  But if we don't"); +	wordWrap("do this, nasty rodent-like people will pirate this game"); +	wordWrap("and a whole generation of talented designers, programmers,"); +	wordWrap("artists, and playtesters will go hungry, and will wander"); +	wordWrap("aimlessly through the land at night searching for peace."); +	wordWrap("So let's grit our teeth and get it over with.  Just get"); +	 +	Common::String line = "out your copy of "; +	line += _hogEntry._bookId == 103 ? "the GAME MANUAL" : "REX'S LOGBOOK"; +	line += ".  See!  That was easy.  "; +	wordWrap(line); + +	line = Common::String::format("Next, just turn to page %d. On line %d, find word number %d, ", +		_hogEntry._pageNum, _hogEntry._lineNum, _hogEntry._wordNum); +	wordWrap(line); + +	wordWrap("and type it on the line below (we',27h,'ve even given you"); +	wordWrap("first letter as a hint).  As soon as you do that, we can get"); +	wordWrap("right into this really COOL adventure game!\n"); +	wordWrap("\n"); +	wordWrap("                    "); +	wordWrap("\n"); +  }  bool CopyProtectionDialog::getHogAnusEntry(HOGANUS &entry) { diff --git a/engines/mads/nebular/dialogs_nebular.h b/engines/mads/nebular/dialogs_nebular.h index 6417c2cdc3..3e28ee39b3 100644 --- a/engines/mads/nebular/dialogs_nebular.h +++ b/engines/mads/nebular/dialogs_nebular.h @@ -30,6 +30,76 @@ namespace MADS {  namespace Nebular { +enum { +	TEXTDIALOG_F8 = 0XF8, +	TEXTDIALOG_F9 = 0XF8, +	TEXTDIALOG_FA = 0XF8, +	TEXTDIALOG_FB = 0XF8, +	TEXTDIALOG_FC = 0XF8, +	TEXTDIALOG_FD = 0XF8, +	TEXTDIALOG_FE = 0XF8, +	TEXTDIALOG_FONT = 0 +}; + +#define TEXT_DIALOG_MAX_LINES 20 + +class TextDialog { +private: +	/** +	 * Increments the number of text lines the text dialog uses +	 */ +	void incNumLines(); + +	/** +	 * Flags the previously added line to be underlined +	 */ +	void underlineLine(); + +	/** +	 * Append text to the currently end line. +	 */ +	void appendLine(const Common::String &line); +protected: +	MADSEngine *_vm; +	Common::Point _position; +	Common::String _fontName; +	int _width; +	int _innerWidth; +	int _lineWidth; +	int _currentX; +	int _numLines; +	int _lineSize; +	Common::String _lines[TEXT_DIALOG_MAX_LINES]; +	int _lineXp[TEXT_DIALOG_MAX_LINES]; +	byte _savedPalette[8 * 3]; + +	/** +	 * Add a new line to the dialog +	 */ +	void addLine(const Common::String &line, bool underline = false); + +	/** +	 * Adds one or more lines, word wrapping the passed text +	 */ +	void wordWrap(const Common::String &line); +public: +	/** +	 * Constructor +	 * @param vm			Engine reference +	 * @param fontName		Font to use for display +	 * @param pos			Position for window top-left +	 * @param maxChars		Horizontal width of window in characters +	 */ +	TextDialog(MADSEngine *vm, const Common::String &fontName, const Common::Point &pos,  +		int maxChars); + +	/** +	 * Destructor +	 */ +	~TextDialog(); + +}; +  struct HOGANUS {  	int _bookId;  	int _pageNum; @@ -38,15 +108,14 @@ struct HOGANUS {  	Common::String _word;  }; -class CopyProtectionDialog { +class CopyProtectionDialog: public TextDialog {  private: -	MADSEngine *_vm;  	HOGANUS _hogEntry;  	/**  	 * Constructor  	 */ -	CopyProtectionDialog(MADSEngine *vm); +	CopyProtectionDialog(MADSEngine *vm, bool priorAnswerWrong);  	/**  	 * Get a random copy protection entry from the HOGANUS resource diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp index 6a5d507c13..c858984a52 100644 --- a/engines/mads/palette.cpp +++ b/engines/mads/palette.cpp @@ -54,18 +54,11 @@ RGBList::~RGBList() {  #define VGA_COLOR_TRANS(x) (x == 0x3f ? 255 : x << 2) -Palette *Palette::init(MADSEngine *vm) { -	if (vm->getGameFeatures() & GF_MADS) { -		return new PaletteMADS(vm); -	} else { -		return new PaletteM4(vm); -	} -} -  Palette::Palette(MADSEngine *vm) : _vm(vm) {  	reset();  	_fading_in_progress = false;  	Common::fill(&_usageCount[0], &_usageCount[PALETTE_COUNT], 0); +	Common::fill(&_mainPalette[0], &_mainPalette[PALETTE_SIZE], 0);  }  void Palette::setPalette(const byte *colors, uint start, uint num) { @@ -245,9 +238,35 @@ void Palette::fadeRange(byte *srcPal, byte *destPal,  int startIndex, int endInd  	_vm->_palette->setPalette(&destPal[startIndex * 3], startIndex, endIndex - startIndex + 1);  } -/*------------------------------------------------------------------------*/ +void Palette::setGradient(byte *palette, int start, int count, int rgbValue1, int rgbValue2) { +	int rgbCtr = 0; +	int rgbDiff = -(rgbValue2 - rgbValue1); +	int rgbCurrent = rgbValue2; + +	if (count >  0) { +		byte *pDest = palette + start * 3; +		int endVal = count - 1; +		int numLeft = count; + +		do { +			pDest[0] = pDest[1] = pDest[2] = rgbCurrent; + +			if (count > 1) { +				rgbCtr += rgbDiff; +				if (rgbCtr >= endVal) { +					do { +						++rgbCurrent; +						rgbCtr += 1 - numLeft; +					} while (rgbCtr >= endVal); +				} +			} + +			pDest += 3; +		} while (--numLeft > 0); +	} +} -byte *PaletteMADS::decodePalette(Common::SeekableReadStream *palStream, int *numColors) { +byte *Palette::decodePalette(Common::SeekableReadStream *palStream, int *numColors) {  	*numColors = palStream->readUint16LE();  	assert(*numColors <= 252); @@ -269,7 +288,7 @@ byte *PaletteMADS::decodePalette(Common::SeekableReadStream *palStream, int *num  	return palData;  } -int PaletteMADS::loadPalette(Common::SeekableReadStream *palStream, int indexStart) { +int Palette::loadPalette(Common::SeekableReadStream *palStream, int indexStart) {  	int colorCount;  	byte *palData = decodePalette(palStream, &colorCount);  	_vm->_palette->setPalette(palData, indexStart, colorCount); @@ -278,7 +297,7 @@ int PaletteMADS::loadPalette(Common::SeekableReadStream *palStream, int indexSta  	return colorCount;  } -void PaletteMADS::setSystemPalette() { +void Palette::setSystemPalette() {  	resetColorCounts();  	byte palData[4 * 3]; diff --git a/engines/mads/palette.h b/engines/mads/palette.h index a97d5de20f..0ef8693a1f 100644 --- a/engines/mads/palette.h +++ b/engines/mads/palette.h @@ -84,13 +84,14 @@ protected:  	byte _fadedPalette[PALETTE_COUNT * 4];  	int _usageCount[PALETTE_COUNT]; -	Palette(MADSEngine *vm);  	void reset();  public: +	byte _mainPalette[PALETTE_SIZE]; +public:  	/** -	 * Creates a new palette instance +	 * Constructor  	 */ -	static Palette *init(MADSEngine *vm); +	Palette(MADSEngine *vm);  	/**  	 * Destructor @@ -153,17 +154,22 @@ public:  	/**  	 * Decode a palette and return it, without affecting the Palette itself  	 */ -	virtual byte *decodePalette(Common::SeekableReadStream *palStream, int *numColors) = 0; +	byte *decodePalette(Common::SeekableReadStream *palStream, int *numColors);  	/**  	 * Loads a palette from a stream  	 */ -	virtual int loadPalette(Common::SeekableReadStream *palStream, int indexStart = 0) = 0; +	int loadPalette(Common::SeekableReadStream *palStream, int indexStart = 0);  	/**  	 * Sets a small set of system/core colors needed by the game  	 */ -	virtual void setSystemPalette() = 0; +	void setSystemPalette(); + +	/** +	 * Update a range of an arbitrary palette +	 */ +	static void setGradient(byte *palette, int start, int count, int rgbValue1, int rgbValue2);  	// Color indexes  	uint8 BLACK; @@ -184,30 +190,6 @@ public:  	uint8 WHITE;  }; -class PaletteMADS: protected Palette { -	friend class Palette; -protected: -	PaletteMADS(MADSEngine *vm): Palette(vm) {} -public: -	virtual byte *decodePalette(Common::SeekableReadStream *palStream, int *numColors); -	virtual int loadPalette(Common::SeekableReadStream *palStream, int indexStart = 0); -	virtual void setSystemPalette(); -}; - -class PaletteM4: protected Palette { -	friend class Palette; -protected: -	PaletteM4(MADSEngine *vm): Palette(vm) {} -public: -	virtual byte *decodePalette(Common::SeekableReadStream *palStream, int *numColors) { -		return nullptr; -	} -	virtual int loadPalette(Common::SeekableReadStream *palStream, int indexStart = 0) { -		return 0; -	} -	virtual void setSystemPalette() {} -}; -  } // End of namespace MADS  #endif /* MADS_PALETTE_H */ | 
