aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/agi/picture.cpp37
-rw-r--r--engines/agi/picture.h14
-rw-r--r--engines/agi/preagi_mickey.cpp2
-rw-r--r--engines/agi/preagi_troll.cpp228
-rw-r--r--engines/agi/preagi_troll.h67
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, &currentOption, numberOfOptions);
- _moves++;
+ if (getMenuSel(menu, &currentOption, 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