diff options
| -rw-r--r-- | engines/agi/picture.cpp | 37 | ||||
| -rw-r--r-- | engines/agi/picture.h | 14 | ||||
| -rw-r--r-- | engines/agi/preagi_mickey.cpp | 2 | ||||
| -rw-r--r-- | engines/agi/preagi_troll.cpp | 228 | ||||
| -rw-r--r-- | engines/agi/preagi_troll.h | 67 | 
5 files changed, 272 insertions, 76 deletions
diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp index 27c19d2eaa..4a7f5f5900 100644 --- a/engines/agi/picture.cpp +++ b/engines/agi/picture.cpp @@ -189,8 +189,11 @@ void PictureMgr::drawLine(int x1, int y1, int x2, int y2) {  void PictureMgr::dynamicDrawLine() {  	int x1, y1, disp, dx, dy; -	x1 = nextByte(); -	y1 = nextByte(); +	if ((x1 = nextByte()) >= _minCommand || +		(y1 = nextByte()) >= _minCommand) { +		_foffs--; +		return; +	}  	putVirtPixel(x1, y1); @@ -221,8 +224,12 @@ void PictureMgr::dynamicDrawLine() {  void PictureMgr::absoluteDrawLine() {  	int x1, y1, x2, y2; -	x1 = nextByte(); -	y1 = nextByte(); +	if ((x1 = nextByte()) >= _minCommand || +		(y1 = nextByte()) >= _minCommand) { +		_foffs--; +		return; +	} +  	putVirtPixel(x1, y1);  	for (;;) { @@ -325,20 +332,24 @@ void PictureMgr::agiFill(unsigned int x, unsigned int y) {  void PictureMgr::xCorner(bool skipOtherCoords) {  	int x1, x2, y1, y2; -	x1 = nextByte(); -	y1 = nextByte(); +	if ((x1 = nextByte()) >= _minCommand || +		(y1 = nextByte()) >= _minCommand) { +		_foffs--; +		return; +	} +  	putVirtPixel(x1, y1);  	for (;;) {  		x2 = nextByte(); +		if (x2 >= _minCommand) +			break; +  		if (skipOtherCoords)  			if (nextByte() >= _minCommand)  				break; -		if (x2 >= _minCommand) -			break; -  		drawLine(x1, y1, x2, y1);  		x1 = x2; @@ -365,8 +376,12 @@ void PictureMgr::xCorner(bool skipOtherCoords) {  void PictureMgr::yCorner(bool skipOtherCoords) {  	int x1, x2, y1, y2; -	x1 = nextByte(); -	y1 = nextByte(); +	if ((x1 = nextByte()) >= _minCommand || +		(y1 = nextByte()) >= _minCommand) { +		_foffs--; +		return; +	} +  	putVirtPixel(x1, y1);  	for (;;) { diff --git a/engines/agi/picture.h b/engines/agi/picture.h index 5d41036a59..28515035e1 100644 --- a/engines/agi/picture.h +++ b/engines/agi/picture.h @@ -50,12 +50,12 @@ enum AgiPictureVersion {  };  enum AgiPictureFlags { -	kPicFNone      = (1 >> 0), -	kPicFCircle    = (1 >> 1), -	kPicFStep      = (1 >> 2), -	kPicFf3Stop    = (1 >> 3), -	kPicFf3Cont    = (1 >> 4), -	kPicFTrollMode = (1 >> 5) +	kPicFNone      = (1 << 0), +	kPicFCircle    = (1 << 1), +	kPicFStep      = (1 << 2), +	kPicFf3Stop    = (1 << 3), +	kPicFf3Cont    = (1 << 4), +	kPicFTrollMode = (1 << 5)  };  class AgiBase; @@ -97,7 +97,7 @@ public:  	void setPattern(uint8 code, uint8 num);  	void setPictureVersion(AgiPictureVersion version); -	void setPictureData(uint8 *data, int len); +	void setPictureData(uint8 *data, int len = 4096);  	void setPictureFlags(int flags) { _flags = flags; } diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index 305e1e0646..edd1b12406 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -801,7 +801,7 @@ void Mickey::drawRoomAnimation() {  			objLight[1] = iColor;  			objLight[4] += 7; -			_vm->_picture->setPictureData(objLight, ARRAYSIZE(objLight)); +			_vm->_picture->setPictureData(objLight);  			_vm->_picture->setPictureFlags(kPicFCircle);  			_vm->_picture->drawPicture();  		} diff --git a/engines/agi/preagi_troll.cpp b/engines/agi/preagi_troll.cpp index 723d275441..3d373d709d 100644 --- a/engines/agi/preagi_troll.cpp +++ b/engines/agi/preagi_troll.cpp @@ -39,8 +39,8 @@ Troll::Troll(PreAgiEngine* vm) : _vm(vm) {  // User Interface -void Troll::pressAnyKey() { -	_vm->drawStr(24, 4, kColorDefault, IDS_TRO_PRESSANYKEY); +void Troll::pressAnyKey(int col) { +	_vm->drawStr(24, col, kColorDefault, IDS_TRO_PRESSANYKEY);  	_vm->_gfx->doUpdate();  	_vm->getSelection(kSelAnyKey);  } @@ -52,7 +52,7 @@ void Troll::drawMenu(const char *szMenu, int iSel) {  	_vm->_gfx->doUpdate();  } -void Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) { +bool Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) {  	Common::Event event;  	int y; @@ -73,14 +73,13 @@ void Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) {  				drawMenu(szMenu, *iSel);  				break;  			case Common::EVENT_LBUTTONUP: -				return; +				return true;  			case Common::EVENT_KEYDOWN:  				switch (event.kbd.keycode) {  				case Common::KEYCODE_t:  				case Common::KEYCODE_f:  					inventory(); -					*iSel = 0; -					drawMenu(szMenu, *iSel); +					return false;  					break;  				case Common::KEYCODE_SPACE:  					*iSel += 1; @@ -92,7 +91,7 @@ void Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) {  					break;  				case Common::KEYCODE_RETURN:  				case Common::KEYCODE_KP_ENTER: -					return; +					return true;  				default:  					break;  				} @@ -104,31 +103,32 @@ void Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) {  		_vm->_system->updateScreen();  		_vm->_system->delayMillis(10);  	} +	 +	return true;  }  // Graphics  void Troll::drawPic(int iPic, bool f3IsCont, bool clr) { -	uint8 frame[] = { -		0xf1, 0x3, 0xf9, 0x0, 0x0, 0x9f, 0x0, 0x9f, 0xa7, 0x0, 0xa7, 0x0, 0x0, 0xff -	}; -  	_vm->_picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT); +	debug(0, "drawPic(%d, %d, %d)", iPic, f3IsCont, clr); +  	if (clr) {  		_vm->clearScreen(0x0f, false);  		_vm->_picture->clear();  	} -	_vm->_picture->setPictureData(frame, ARRAYSIZE(frame)); +	_vm->_picture->setPictureData(_gameData + IDO_TRO_FRAMEPIC);  	_vm->_picture->drawPicture(); -	_vm->_picture->setPictureData(_gameData + _pictureOffsets[iPic], 4096); +	_vm->_picture->setPictureData(_gameData + _pictureOffsets[iPic]); -	if (f3IsCont) +	if (f3IsCont) {  		_vm->_picture->setPictureFlags(kPicFf3Cont); -	else +	} else {  		_vm->_picture->setPictureFlags(kPicFf3Stop); +	}  	_vm->_picture->drawPicture(); @@ -139,16 +139,28 @@ void Troll::drawPic(int iPic, bool f3IsCont, bool clr) {  // Game Logic  void Troll::inventory() { -	char szMissing[40]; +	char tmp[40]; +	int n;  	_vm->clearScreen(0x07);  	_vm->drawStr(1, 12, kColorDefault, IDS_TRO_TREASURE_0);  	_vm->drawStr(2, 12, kColorDefault, IDS_TRO_TREASURE_1); + +	for (int i = 0; i < IDI_TRO_MAX_TREASURE - _treasuresLeft; i++) { +		n = _inventory[i] - 1; + +		sprintf(tmp, " %2d ", i + 1); + +		_vm->drawStr(2 + i, 10, _items[n].bg << 4 | 0x0f,  tmp); +		_vm->drawStr(2 + i, 14, _items[n].bg << 4 | _items[n].fg,  _items[n].name); +	} + +  	switch (_treasuresLeft) {  	case 1: -		sprintf(szMissing, IDS_TRO_TREASURE_5, _treasuresLeft); -		_vm->drawStr(20, 10,kColorDefault,  szMissing); +		sprintf(tmp, IDS_TRO_TREASURE_5, _treasuresLeft); +		_vm->drawStr(20, 10, kColorDefault, tmp);  		break;  	case 0:  		_vm->drawStr(20, 1, kColorDefault, IDS_TRO_TREASURE_6); @@ -156,14 +168,12 @@ void Troll::inventory() {  	case IDI_TRO_MAX_TREASURE:  		_vm->drawStr(3, 17, kColorDefault, IDS_TRO_TREASURE_2);  	default: -		sprintf(szMissing, IDS_TRO_TREASURE_4, _treasuresLeft); -		_vm->drawStr(20, 10,kColorDefault,  szMissing); +		sprintf(tmp, IDS_TRO_TREASURE_4, _treasuresLeft); +		_vm->drawStr(20, 10, kColorDefault, tmp);  		break;  	}	 -	_vm->drawStr(24, 6, kColorDefault, IDS_TRO_PRESSANYKEY); -	_vm->_gfx->doUpdate(); -	_vm->getSelection(kSelAnyKey); +	pressAnyKey(6);  }  void Troll::waitAnyKeyIntro() { @@ -315,7 +325,7 @@ void Troll::tutorial() {  	_vm->clearScreen(0x2A);  	_vm->drawStr(2, 1, kColorDefault, IDS_TRO_TUTORIAL_19);  	for (int i = 0; i < IDI_TRO_MAX_TREASURE; i++) -		_vm->drawStr(19 - i, 11, kColorDefault, (const char *)IDS_TRO_NAME_TREASURE[i]); +		_vm->drawStr(19 - i, 11, kColorDefault, _items[i].name);  	_vm->_gfx->doUpdate(); @@ -370,16 +380,41 @@ void Troll::gameOver() {  	pressAnyKey();  } +void Troll::drawTroll() { +	warning("STUB: drawTroll()"); +} +  int Troll::drawRoom(char *menu) {  	int n; +	bool contFlag = false; -	drawPic(_locationDescIndex, false, true); -	_vm->_gfx->doUpdate(); +	if (_locationDescIndex == 1) { +		_vm->_picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT); +		_vm->clearScreen(0x00, false); +		_vm->_picture->clear(); +	} else { -	// TODO: Troll +		if (_locationDescIndex != 42) { +			if (_roomPicDeltas[_locationDescIndex]) { +				contFlag = true; +			} +		} + +		drawPic(_locationDescIndex, contFlag, true); + +		if (_locationDescIndex == 42) { +			drawPic(44, false, false); // don't clear +		} else { +			if (!_isTrollAway) { +				drawTroll(); +			} +		} +	} + +	_vm->_gfx->doUpdate();  	char tmp[10]; -	strncat(menu, (char*)_gameData + IDO_TRO_LOCMESSAGES + _locationDescIndex * 39, 39); +	strncat(menu, (char*)_gameData + _locMessagesIdx[_locationDescIndex], 39);  	for (int i = 0; i < 3; i++) {  		if (_roomDescs[_currentRoom - 1].options[i]) { @@ -395,6 +430,64 @@ int Troll::drawRoom(char *menu) {  	return n;  } +void Troll::playTune(int tune, int len) { +	warning("STUB: playTune(%d, %d)", tune, len); +} + +void Troll::pickupTreasure() { +	char tmp[40]; + +	_inventory[IDI_TRO_MAX_TREASURE - _treasuresLeft] = _roomDescIndex; + +	_roomDescIndex += 16; + +	if (_locationDescIndex != 24) { +		_vm->clearTextArea(); +		drawPic(_locationDescIndex, false, true); +		_vm->_gfx->doUpdate(); +	} + +	printUserMessage(); + +	_vm->clearTextArea(); + +	_treasuresLeft--; + +	switch (_treasuresLeft) { +	case 1: +		_vm->drawStr(22, 1, kColorDefault, IDS_TRO_TREASURE_7); +		break; +	case 0: +		_vm->drawStr(22, 1, kColorDefault, IDS_TRO_TREASURE_8); +		_vm->drawStr(23, 4, kColorDefault, IDS_TRO_TREASURE_9); + +		_roomStates[6] = 1; + +		_locMessagesIdx[6] = IDO_TRO_ALLTREASURES; +		break; +	default: +		sprintf(tmp, IDS_TRO_TREASURE_3, _treasuresLeft); +		_vm->drawStr(22, 1, kColorDefault, tmp); +		break; +	} + +	pressAnyKey(); +} + +void Troll::printUserMessage() { +	int i; + +	for (i = 0; i < _userMessages[_roomDescIndex - 1].num; i++) { +		_vm->drawStr(21 + i, 1, kColorDefault, _userMessages[_roomDescIndex - 1].msg[i]); +	} +		 +	if (_roomDescIndex == 34) { +		for (i = 0; i < 2; i++) +			playTune(5, 11); +	} +	pressAnyKey(); +} +  void Troll::gameLoop() {  	bool done = false;  	char menu[160+5]; @@ -405,8 +498,11 @@ void Troll::gameLoop() {  	_treasuresLeft = IDI_TRO_MAX_TREASURE;  	_haveFlashlight = false;  	_locationDescIndex = 0; +	_isTrollAway = true;  	memset(_roomStates, 0, sizeof(_roomStates)); + +	memset(_inventory, 0, sizeof(_inventory));  	while (!done) {  		*menu = 0; @@ -415,15 +511,47 @@ void Troll::gameLoop() {  		numberOfOptions = drawRoom(menu); -		getMenuSel(menu, ¤tOption, numberOfOptions); -		_moves++; +		if (getMenuSel(menu, ¤tOption, numberOfOptions)) { +			_moves++; +		} else { +			continue; +		} + +		_roomDescIndex = _roomDescs[_currentRoom - 1].roomDescIndex[currentOption];  		switch(_roomDescs[_currentRoom - 1].optionTypes[currentOption]) {  		case OT_GO: -			_locationDescIndex = _roomDescs[_currentRoom - 1].roomDescIndex[currentOption]; +			_locationDescIndex = _roomDescIndex;  			_currentRoom = _roomPicStartIdx[_locationDescIndex];  			_currentRoom += _roomStates[_locationDescIndex];  			break; +		case OT_GET: +			if (!_isTrollAway) { +				_roomDescIndex = 34; +				printUserMessage(); +			} else { +				for (int i = 0; i < 4; i++) { +					playTune(1, 3); +					// delayMillis() +				} + +				_roomStates[_locationDescIndex] = 1; +				_roomPicDeltas[_locationDescIndex] = 0; + +				_currentRoom++; + +				if (_roomConnects[_roomDescIndex - 1] != 0xff) { +					_roomStates[_roomConnects[_roomDescIndex - 1]] = 1; +				} + +				if (_roomDescIndex == 1) +					_haveFlashlight = true; + +				_locMessagesIdx[_locationDescIndex] = IDO_TRO_LOCMESSAGES +  +					(_roomDescIndex + 42) * 39; + +				pickupTreasure(); +			}  		default:  			break;  		} @@ -440,16 +568,20 @@ void Troll::fillOffsets() {  	for (i = 0; i < IDI_TRO_NUM_OPTIONS; i++)  		_options[i] = READ_LE_UINT16(_gameData + IDO_TRO_OPTIONS + i * 2); -	for (i = 0; i < IDI_TRO_NUM_NUMROOMS; i++) +	for (i = 0; i < IDI_TRO_NUM_NUMROOMS; i++) {  		_roomPicStartIdx[i] = _gameData[IDO_TRO_PICSTARTIDX + i]; -} +		_roomPicDeltas[i] = _gameData[IDO_TRO_ROOMPICDELTAS + i]; +		_roomConnects[i] = _gameData[IDO_TRO_ROOMCONNECTS + i]; +	} + +	for (i = 0; i < IDI_TRO_NUM_LOCDESCS; i++) +		_locMessagesIdx[i] = IDO_TRO_LOCMESSAGES + i * 39; -void Troll::fillRoomDescs() {  	int start = READ_LE_UINT16(_gameData + IDO_TRO_ROOMDESCS);  	int ptr;  	int j; -	for (int i = 0; i < IDI_TRO_NUM_ROOMDESCS; i++) { +	for (i = 0; i < IDI_TRO_NUM_ROOMDESCS; i++, start += 2) {  		ptr = READ_LE_UINT16(_gameData + start);  		for (j = 0; j < 3; j++) @@ -476,8 +608,29 @@ void Troll::fillRoomDescs() {  		for (j = 0; j < 3; j++)  			_roomDescs[i].roomDescIndex[j] = _gameData[ptr++]; -		 -		start += 2; +	} + +	start = IDO_TRO_USERMESSAGES; + +	for (i = 0; i < IDI_TRO_NUM_USERMSGS; i++, start += 2) { +		ptr = READ_LE_UINT16(_gameData + start); + +		_userMessages[i].num = _gameData[ptr++]; + +		for (j = 0; j < _userMessages[i].num; j++, ptr += 39) { +			memcpy(_userMessages[i].msg[j], _gameData + ptr, 39); +			_userMessages[i].msg[j][39] = 0; +		} +	} + +	start = IDO_TRO_ITEMS; + +	for (i = 0; i < IDI_TRO_MAX_TREASURE; i++, start += 2) { +		ptr = READ_LE_UINT16(_gameData + start); +		_items[i].bg = _gameData[ptr++]; +		_items[i].fg = _gameData[ptr++]; +		memcpy(_items[i].name, _gameData + ptr, 15); +		_items[i].name[15] = 0;  	}  } @@ -497,7 +650,6 @@ void Troll::init() {  	infile.close();  	fillOffsets(); -	fillRoomDescs();  }  void Troll::run() { diff --git a/engines/agi/preagi_troll.h b/engines/agi/preagi_troll.h index a064f4eb04..ca1dfb08da 100644 --- a/engines/agi/preagi_troll.h +++ b/engines/agi/preagi_troll.h @@ -78,7 +78,7 @@ namespace Agi {  #define IDS_TRO_TREASURE_0	"TREASURES FOUND"  #define IDS_TRO_TREASURE_1	"---------------"  #define IDS_TRO_TREASURE_2	"NONE" -#define IDS_TRO_TREASURE_3	"THERE ARE STILL" +#define IDS_TRO_TREASURE_3	"THERE ARE STILL %d TREASURES TO FIND"  #define IDS_TRO_TREASURE_4	"%d TREASURES TO FIND"  #define IDS_TRO_TREASURE_5	"%d TREASURE TO FIND"  #define IDS_TRO_TREASURE_6	"YOU HAVE FOUND ALL OF THE TREASURES!!" @@ -89,13 +89,6 @@ namespace Agi {  #define IDS_TRO_GAMEOVER_0	"You took %d moves to complete TROLL'S"  #define IDS_TRO_GAMEOVER_1	"TALE. Do you think you can do better?" -const char IDS_TRO_NAME_TREASURE[][16] = { -	"  FLASHLIGHT   ", "  BAG OF GOLD  ", " BOX OF JEWELS ", "  DIAMOND RING ", -	" CANDY SUCKER  ", "DOLLAR AND CENT", "     FIDDLE    ", "BAG OF PENNIES ", -	" TREASURE CHEST", "     PENNY     ", "  SILVER CUP   ", "    NECKLACE   ", -	"     SHELL     ", "  GOLD BRICK   ", "     GIFT      ", " POT OF MONEY  " -}; -  // picture  #define IDI_TRO_PICNUM 47 @@ -121,16 +114,26 @@ const char IDS_TRO_NAME_TREASURE[][16] = {  #define IDI_TRO_NUM_OPTIONS		129  #define IDI_TRO_NUM_NUMROOMS	43 +#define IDI_TRO_NUM_USERMSGS    34 + +#define IDI_TRO_NUM_LOCDESCS    59 +  // offsets  #define IDA_TRO_BINNAME "troll.exe" -#define IDO_TRO_DATA_START  0x1960 -#define IDO_TRO_PIC_START	0x3EF5 -#define IDO_TRO_LOCMESSAGES 0x1F7C -#define IDO_TRO_ROOMDESCS   0x0082 -#define IDO_TRO_OPTIONS     0x0364 -#define IDO_TRO_PICSTARTIDX 0x02CD +#define IDO_TRO_DATA_START    0x1960 +#define IDO_TRO_PIC_START	  0x3EF5 +#define IDO_TRO_LOCMESSAGES   0x1F7C +#define IDO_TRO_USERMESSAGES  0x34A4 +#define IDO_TRO_ROOMDESCS     0x0082 +#define IDO_TRO_OPTIONS       0x0364 +#define IDO_TRO_PICSTARTIDX   0x02CD +#define IDO_TRO_ROOMPICDELTAS 0x030C +#define IDO_TRO_ALLTREASURES  0x3B24 +#define IDO_TRO_ITEMS         0x34E8 +#define IDO_TRO_FRAMEPIC      0x3EC2 +#define IDO_TRO_ROOMCONNECTS  0x02FA  enum OptionType {  	OT_GO, @@ -145,6 +148,17 @@ struct RoomDesc {  	int roomDescIndex[3];  }; +struct UserMsg { +	int num; +	char msg[3][40]; +}; + +struct Item { +	byte bg; +	byte fg; +	char name[16]; +}; +  class Troll {  	friend class PreAgiEngine;  public: @@ -159,11 +173,13 @@ private:  	int _treasuresLeft;  	int _locationDescIndex;  	int _numberOfOptions; +	int _roomDescIndex; + +	bool _isTrollAway;  	bool _haveFlashlight; -	RoomDesc _roomDescs[IDI_TRO_NUM_ROOMDESCS]; -	int _options[IDI_TRO_NUM_OPTIONS]; +	int _inventory[IDI_TRO_MAX_TREASURE];  	byte *_gameData; @@ -171,29 +187,42 @@ private:  	void intro();  	void drawPic(int iPic, bool f3IsCont, bool clear); +	void drawTroll();  	void gameLoop();  	void gameOver();  	void tutorial();  	void credits();  	void inventory(); +	void pickupTreasure();  	int drawRoom(char *menu); +	void printUserMessage(); -	void pressAnyKey(); +	void pressAnyKey(int col = 4);  	void waitAnyKeyIntro(); -	void getMenuSel(const char*, int*, int); +	void playTune(int tune, int len); + +	bool getMenuSel(const char*, int*, int);  	void drawMenu(const char *szMenu, int iSel);  	void fillOffsets(); -	void fillRoomDescs();  private: +	// These are come from game data +  	int _pictureOffsets[IDI_TRO_PICNUM];  	int _roomPicStartIdx[IDI_TRO_NUM_NUMROOMS]; +	int _roomPicDeltas[IDI_TRO_NUM_NUMROOMS];  	int _roomStates[IDI_TRO_NUM_NUMROOMS]; +	UserMsg _userMessages[IDI_TRO_NUM_USERMSGS]; +	int _locMessagesIdx[IDI_TRO_NUM_LOCDESCS]; +	RoomDesc _roomDescs[IDI_TRO_NUM_ROOMDESCS]; +	int _options[IDI_TRO_NUM_OPTIONS]; +	Item _items[IDI_TRO_MAX_TREASURE]; +	int _roomConnects[IDI_TRO_NUM_OPTIONS];  };  } // End of namespace Agi  | 
