mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-29 13:16:18 +00:00
8a595e7771
- graphics code fully rewritten - Apple IIgs font support - Amiga Topaz support - Word parser rewritten - menu code rewritten - removed forced 2 second delay on all room changes replaced with heuristic to detect situations, where it's required - lots of naming cleanup - new console commands show_map, screenobj, vmvars and vmflags - all sorts of hacks/workarounds removed - added SCI wait mouse cursor - added Apple IIgs mouse cursor - added Atari ST mouse cursor - added Amiga/Apple IIgs transition - added Atari ST transition - user can select another render mode and use Apple IIgs palette + transition for PC versions - inventory screen rewritten - SetSimple command now properly implemented - PreAGI Mickey: Sierra logo now shown - saved games: now saving controller key mapping also saving automatic save data (SetSimple command) - fixed invalid memory access when saving games (31 bytes were saved using Common::String c_ptr() Special Thanks to: - fuzzie for helping out with the Apple IIgs font + valgrind - eriktorbjorn for helping out with valgrind - LordHoto for figuring out the code, that caused invalid memory access in the original code, when saving a game - sev for help out with reversing the Amiga transition currently missing: - mouse support for menu - mouse support for system dialogs - predictive dialog support
782 lines
17 KiB
C++
782 lines
17 KiB
C++
/* 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 "agi/preagi.h"
|
|
#include "agi/preagi_troll.h"
|
|
#include "agi/graphics.h"
|
|
|
|
#include "common/events.h"
|
|
#include "common/textconsole.h"
|
|
|
|
#include "graphics/cursorman.h"
|
|
|
|
namespace Agi {
|
|
|
|
TrollEngine::TrollEngine(OSystem *syst, const AGIGameDescription *gameDesc) : PreAgiEngine(syst, gameDesc) {
|
|
}
|
|
|
|
TrollEngine::~TrollEngine() {
|
|
}
|
|
|
|
// User Interface
|
|
|
|
void TrollEngine::pressAnyKey(int col) {
|
|
drawStr(24, col, kColorDefault, IDS_TRO_PRESSANYKEY);
|
|
g_system->updateScreen();
|
|
getSelection(kSelAnyKey);
|
|
}
|
|
|
|
void TrollEngine::drawMenu(const char *szMenu, int iSel) {
|
|
clearTextArea();
|
|
drawStr(21, 0, kColorDefault, szMenu);
|
|
drawStr(22 + iSel, 0, kColorDefault, " *");
|
|
g_system->updateScreen();
|
|
}
|
|
|
|
bool TrollEngine::getMenuSel(const char *szMenu, int *iSel, int nSel) {
|
|
Common::Event event;
|
|
int y;
|
|
|
|
drawMenu(szMenu, *iSel);
|
|
|
|
while (!shouldQuit()) {
|
|
while (_system->getEventManager()->pollEvent(event)) {
|
|
switch (event.type) {
|
|
case Common::EVENT_RTL:
|
|
case Common::EVENT_QUIT:
|
|
return 0;
|
|
case Common::EVENT_MOUSEMOVE:
|
|
y = event.mouse.y / 8;
|
|
|
|
if (y >= 22)
|
|
if (nSel > y - 22)
|
|
*iSel = y - 22;
|
|
|
|
drawMenu(szMenu, *iSel);
|
|
break;
|
|
case Common::EVENT_LBUTTONUP:
|
|
return true;
|
|
case Common::EVENT_KEYDOWN:
|
|
switch (event.kbd.keycode) {
|
|
case Common::KEYCODE_t:
|
|
case Common::KEYCODE_f:
|
|
inventory();
|
|
|
|
return false;
|
|
case Common::KEYCODE_DOWN:
|
|
case Common::KEYCODE_SPACE:
|
|
*iSel += 1;
|
|
|
|
if (*iSel == nSel)
|
|
*iSel = IDI_TRO_SEL_OPTION_1;
|
|
|
|
drawMenu(szMenu, *iSel);
|
|
break;
|
|
case Common::KEYCODE_UP:
|
|
*iSel -= 1;
|
|
|
|
if (*iSel == IDI_TRO_SEL_OPTION_1 - 1)
|
|
*iSel = nSel - 1;
|
|
|
|
drawMenu(szMenu, *iSel);
|
|
break;
|
|
case Common::KEYCODE_RETURN:
|
|
case Common::KEYCODE_KP_ENTER:
|
|
return true;
|
|
case Common::KEYCODE_s:
|
|
if (event.kbd.hasFlags(Common::KBD_CTRL)) {
|
|
if (_soundOn) {
|
|
playTune(2, 1);
|
|
_soundOn = !_soundOn;
|
|
} else {
|
|
_soundOn = !_soundOn;
|
|
playTune(3, 1);
|
|
}
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
_system->updateScreen();
|
|
_system->delayMillis(10);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Graphics
|
|
|
|
void TrollEngine::drawPic(int iPic, bool f3IsCont, bool clr, bool troll) {
|
|
_picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT);
|
|
|
|
if (clr) {
|
|
clearScreen(0x0f, false);
|
|
_picture->clear();
|
|
}
|
|
|
|
_picture->setPictureData(_gameData + IDO_TRO_FRAMEPIC);
|
|
_picture->drawPicture();
|
|
|
|
_picture->setPictureData(_gameData + _pictureOffsets[iPic]);
|
|
|
|
int addFlag = 0;
|
|
|
|
if (troll)
|
|
addFlag = kPicFTrollMode;
|
|
|
|
if (f3IsCont) {
|
|
_picture->setPictureFlags(kPicFf3Cont | addFlag);
|
|
} else {
|
|
_picture->setPictureFlags(kPicFf3Stop | addFlag);
|
|
}
|
|
|
|
_picture->drawPicture();
|
|
|
|
_picture->showPic(); // TODO: *HAVE* to add coordinates + height/width!!
|
|
g_system->updateScreen();
|
|
}
|
|
|
|
// Game Logic
|
|
|
|
void TrollEngine::inventory() {
|
|
char tmp[40];
|
|
int n;
|
|
|
|
clearScreen(0x07);
|
|
drawStr(1, 12, kColorDefault, IDS_TRO_TREASURE_0);
|
|
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);
|
|
|
|
drawStr(2 + i, 10, _items[n].bg << 4 | 0x0f, tmp);
|
|
drawStr(2 + i, 14, _items[n].bg << 4 | _items[n].fg, _items[n].name);
|
|
}
|
|
|
|
|
|
switch (_treasuresLeft) {
|
|
case 1:
|
|
sprintf(tmp, IDS_TRO_TREASURE_5, _treasuresLeft);
|
|
drawStr(20, 10, kColorDefault, tmp);
|
|
break;
|
|
case 0:
|
|
drawStr(20, 1, kColorDefault, IDS_TRO_TREASURE_6);
|
|
break;
|
|
case IDI_TRO_MAX_TREASURE:
|
|
drawStr(3, 17, kColorDefault, IDS_TRO_TREASURE_2);
|
|
break;
|
|
default:
|
|
sprintf(tmp, IDS_TRO_TREASURE_4, _treasuresLeft);
|
|
drawStr(20, 10, kColorDefault, tmp);
|
|
break;
|
|
}
|
|
|
|
pressAnyKey(6);
|
|
}
|
|
|
|
void TrollEngine::waitAnyKeyIntro() {
|
|
Common::Event event;
|
|
int iMsg = 0;
|
|
|
|
while (!shouldQuit()) {
|
|
while (_system->getEventManager()->pollEvent(event)) {
|
|
switch (event.type) {
|
|
case Common::EVENT_RTL:
|
|
case Common::EVENT_QUIT:
|
|
case Common::EVENT_LBUTTONUP:
|
|
case Common::EVENT_KEYDOWN:
|
|
return;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (iMsg) {
|
|
case 200:
|
|
iMsg = 0;
|
|
// fall through
|
|
case 0:
|
|
drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_2);
|
|
g_system->updateScreen();
|
|
break;
|
|
case 100:
|
|
drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_3);
|
|
g_system->updateScreen();
|
|
break;
|
|
}
|
|
|
|
iMsg++;
|
|
|
|
_system->updateScreen();
|
|
_system->delayMillis(10);
|
|
}
|
|
}
|
|
|
|
void TrollEngine::credits() {
|
|
clearScreen(0x07);
|
|
|
|
drawStr(1, 2, kColorDefault, IDS_TRO_CREDITS_0);
|
|
|
|
int color = 10;
|
|
char str[2];
|
|
|
|
str[1] = 0;
|
|
|
|
for (uint i = 0; i < strlen(IDS_TRO_CREDITS_1); i++) {
|
|
str[0] = IDS_TRO_CREDITS_1[i];
|
|
drawStr(7, 19 + i, color++, str);
|
|
if (color > 15)
|
|
color = 9;
|
|
}
|
|
|
|
drawStr(8, 19, kColorDefault, IDS_TRO_CREDITS_2);
|
|
|
|
drawStr(13, 11, 9, IDS_TRO_CREDITS_3);
|
|
drawStr(15, 8, 10, IDS_TRO_CREDITS_4);
|
|
drawStr(17, 7, 12, IDS_TRO_CREDITS_5);
|
|
drawStr(19, 2, 14, IDS_TRO_CREDITS_6);
|
|
|
|
g_system->updateScreen();
|
|
|
|
pressAnyKey();
|
|
}
|
|
|
|
void TrollEngine::tutorial() {
|
|
bool done = false;
|
|
int iSel = 0;
|
|
//char szTreasure[16] = {0};
|
|
|
|
while (!shouldQuit()) {
|
|
clearScreen(0xFF);
|
|
|
|
printStr(IDS_TRO_TUTORIAL_0);
|
|
getSelection(kSelSpace);
|
|
|
|
clearScreen(0x55);
|
|
setDefaultTextColor(0x0F);
|
|
|
|
done = false;
|
|
while (!done && !shouldQuit()) {
|
|
getMenuSel(IDS_TRO_TUTORIAL_1, &iSel, IDI_TRO_MAX_OPTION);
|
|
|
|
switch (iSel) {
|
|
case IDI_TRO_SEL_OPTION_1:
|
|
clearScreen(0x22, false);
|
|
g_system->updateScreen();
|
|
break;
|
|
case IDI_TRO_SEL_OPTION_2:
|
|
clearScreen(0x00, false);
|
|
g_system->updateScreen();
|
|
break;
|
|
case IDI_TRO_SEL_OPTION_3:
|
|
done = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// do you need more practice ?
|
|
clearScreen(0x4F);
|
|
drawStr(7, 4, kColorDefault, IDS_TRO_TUTORIAL_5);
|
|
drawStr(9, 4, kColorDefault, IDS_TRO_TUTORIAL_6);
|
|
g_system->updateScreen();
|
|
|
|
if (!getSelection(kSelYesNo))
|
|
break;
|
|
}
|
|
|
|
// show info texts
|
|
clearScreen(0x5F);
|
|
drawStr(4, 1, kColorDefault, IDS_TRO_TUTORIAL_7);
|
|
drawStr(5, 1, kColorDefault, IDS_TRO_TUTORIAL_8);
|
|
g_system->updateScreen();
|
|
pressAnyKey();
|
|
|
|
clearScreen(0x2F);
|
|
drawStr(6, 1, kColorDefault, IDS_TRO_TUTORIAL_9);
|
|
g_system->updateScreen();
|
|
pressAnyKey();
|
|
|
|
clearScreen(0x19);
|
|
drawStr(7, 1, kColorDefault, IDS_TRO_TUTORIAL_10);
|
|
drawStr(8, 1, kColorDefault, IDS_TRO_TUTORIAL_11);
|
|
g_system->updateScreen();
|
|
pressAnyKey();
|
|
|
|
clearScreen(0x6E);
|
|
drawStr(9, 1, kColorDefault, IDS_TRO_TUTORIAL_12);
|
|
drawStr(10, 1, kColorDefault, IDS_TRO_TUTORIAL_13);
|
|
g_system->updateScreen();
|
|
pressAnyKey();
|
|
|
|
clearScreen(0x4C);
|
|
drawStr(11, 1, kColorDefault, IDS_TRO_TUTORIAL_14);
|
|
drawStr(12, 1, kColorDefault, IDS_TRO_TUTORIAL_15);
|
|
g_system->updateScreen();
|
|
pressAnyKey();
|
|
|
|
clearScreen(0x5D);
|
|
drawStr(13, 1, kColorDefault, IDS_TRO_TUTORIAL_16);
|
|
drawStr(14, 1, kColorDefault, IDS_TRO_TUTORIAL_17);
|
|
drawStr(15, 1, kColorDefault, IDS_TRO_TUTORIAL_18);
|
|
g_system->updateScreen();
|
|
pressAnyKey();
|
|
|
|
// show treasures
|
|
clearScreen(0x2A);
|
|
drawStr(2, 1, kColorDefault, IDS_TRO_TUTORIAL_19);
|
|
for (int i = 0; i < IDI_TRO_MAX_TREASURE; i++)
|
|
drawStr(19 - i, 11, kColorDefault, _items[i].name);
|
|
|
|
g_system->updateScreen();
|
|
|
|
pressAnyKey();
|
|
}
|
|
|
|
void TrollEngine::intro() {
|
|
// sierra on-line presents
|
|
clearScreen(0x2F);
|
|
drawStr(9, 10, kColorDefault, IDS_TRO_INTRO_0);
|
|
drawStr(14, 15, kColorDefault, IDS_TRO_INTRO_1);
|
|
g_system->updateScreen();
|
|
_system->delayMillis(3200);
|
|
|
|
CursorMan.showMouse(true);
|
|
|
|
// Draw logo
|
|
setDefaultTextColor(0x0f);
|
|
drawPic(45, false, true);
|
|
g_system->updateScreen();
|
|
|
|
// wait for keypress and alternate message
|
|
waitAnyKeyIntro();
|
|
|
|
// have you played this game before?
|
|
drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_4);
|
|
drawStr(23, 6, kColorDefault, IDS_TRO_INTRO_5);
|
|
g_system->updateScreen();
|
|
|
|
if (!getSelection(kSelYesNo))
|
|
tutorial();
|
|
|
|
credits();
|
|
}
|
|
|
|
void TrollEngine::gameOver() {
|
|
// We do a check to see if the game should quit. Without this, the game show the picture, plays the
|
|
// music, and then quits. So if the game is quitting, we shouldn't run the "game over" part.
|
|
if (shouldQuit())
|
|
return;
|
|
|
|
char szMoves[40];
|
|
|
|
clearTextArea();
|
|
drawPic(42, true, true);
|
|
|
|
playTune(4, 25);
|
|
|
|
printUserMessage(16);
|
|
|
|
printUserMessage(33);
|
|
|
|
clearTextArea();
|
|
|
|
drawPic(46, true, true);
|
|
|
|
sprintf(szMoves, IDS_TRO_GAMEOVER_0, _moves);
|
|
drawStr(21, 1, kColorDefault, szMoves);
|
|
drawStr(22, 1, kColorDefault, IDS_TRO_GAMEOVER_1);
|
|
g_system->updateScreen();
|
|
|
|
pressAnyKey();
|
|
}
|
|
|
|
void TrollEngine::drawTroll() {
|
|
for (int i = 0; i < IDI_TRO_NUM_NONTROLL; i++)
|
|
if (_currentRoom == _nonTrollRooms[i]) {
|
|
_isTrollAway = true;
|
|
return;
|
|
}
|
|
|
|
drawPic(43, false, false, true);
|
|
}
|
|
|
|
int TrollEngine::drawRoom(char *menu) {
|
|
int n = 0;
|
|
bool contFlag = false;
|
|
|
|
if (_currentRoom == 1) {
|
|
_picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT);
|
|
clearScreen(0x00, false);
|
|
_picture->clear();
|
|
} else {
|
|
|
|
if (_currentRoom != 42) {
|
|
if (_roomPicDeltas[_currentRoom]) {
|
|
contFlag = true;
|
|
}
|
|
}
|
|
|
|
drawPic(_currentRoom, contFlag, true);
|
|
g_system->updateScreen();
|
|
|
|
if (_currentRoom == 42) {
|
|
drawPic(44, false, false); // don't clear
|
|
} else {
|
|
if (!_isTrollAway) {
|
|
drawTroll();
|
|
}
|
|
}
|
|
}
|
|
|
|
g_system->updateScreen();
|
|
|
|
char tmp[10];
|
|
strncat(menu, (char *)_gameData + _locMessagesIdx[_currentRoom], 39);
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
if (_roomDescs[_roomPicture - 1].options[i]) {
|
|
sprintf(tmp, "\n %d.", i);
|
|
strcat(menu, tmp);
|
|
|
|
strncat(menu, (char *)_gameData + _options[_roomDescs[_roomPicture - 1].options[i]- 1], 35);
|
|
|
|
n = i + 1;
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
void TrollEngine::playTune(int tune, int len) {
|
|
if (!_soundOn)
|
|
return;
|
|
|
|
int freq, duration;
|
|
int ptr = _tunes[tune - 1];
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
freq = READ_LE_UINT16(_gameData + ptr);
|
|
ptr += 2;
|
|
duration = READ_LE_UINT16(_gameData + ptr);
|
|
ptr += 2;
|
|
|
|
playNote(freq, duration);
|
|
}
|
|
}
|
|
|
|
void TrollEngine::pickupTreasure(int treasureId) {
|
|
char tmp[40];
|
|
|
|
_inventory[IDI_TRO_MAX_TREASURE - _treasuresLeft] = treasureId;
|
|
|
|
if (_currentRoom != 24) {
|
|
clearTextArea();
|
|
drawPic(_currentRoom, false, true);
|
|
g_system->updateScreen();
|
|
}
|
|
|
|
printUserMessage(treasureId + 16);
|
|
|
|
clearTextArea();
|
|
|
|
_treasuresLeft--;
|
|
|
|
switch (_treasuresLeft) {
|
|
case 1:
|
|
drawStr(22, 1, kColorDefault, IDS_TRO_TREASURE_7);
|
|
break;
|
|
case 0:
|
|
drawStr(22, 1, kColorDefault, IDS_TRO_TREASURE_8);
|
|
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);
|
|
drawStr(22, 1, kColorDefault, tmp);
|
|
break;
|
|
}
|
|
|
|
pressAnyKey();
|
|
}
|
|
|
|
void TrollEngine::printUserMessage(int msgId) {
|
|
int i;
|
|
|
|
clearTextArea();
|
|
|
|
for (i = 0; i < _userMessages[msgId - 1].num; i++) {
|
|
drawStr(21 + i, 1, kColorDefault, _userMessages[msgId - 1].msg[i]);
|
|
}
|
|
|
|
if (msgId == 34) {
|
|
for (i = 0; i < 2; i++)
|
|
playTune(5, 11);
|
|
}
|
|
pressAnyKey();
|
|
}
|
|
|
|
void TrollEngine::gameLoop() {
|
|
bool done = false;
|
|
char menu[160+5];
|
|
int currentOption, numberOfOptions;
|
|
int roomParam;
|
|
int haveFlashlight;
|
|
|
|
_moves = 0;
|
|
_roomPicture = 1;
|
|
_treasuresLeft = IDI_TRO_MAX_TREASURE;
|
|
haveFlashlight = false;
|
|
_currentRoom = 0;
|
|
_isTrollAway = true;
|
|
_soundOn = true;
|
|
|
|
memset(_roomStates, 0, sizeof(_roomStates));
|
|
|
|
memset(_inventory, 0, sizeof(_inventory));
|
|
|
|
while (!done && !shouldQuit()) {
|
|
*menu = 0;
|
|
|
|
currentOption = 0;
|
|
|
|
numberOfOptions = drawRoom(menu);
|
|
|
|
if (getMenuSel(menu, ¤tOption, numberOfOptions)) {
|
|
_moves++;
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
roomParam = _roomDescs[_roomPicture - 1].roomDescIndex[currentOption];
|
|
|
|
switch (_roomDescs[_roomPicture - 1].optionTypes[currentOption]) {
|
|
case OT_FLASHLIGHT:
|
|
if (!haveFlashlight) {
|
|
printUserMessage(13);
|
|
break;
|
|
}
|
|
// fall down
|
|
case OT_GO:
|
|
_currentRoom = roomParam;
|
|
_roomPicture = _roomPicStartIdx[_currentRoom];
|
|
_roomPicture += _roomStates[_currentRoom];
|
|
|
|
if (_currentRoom < 6 || _treasuresLeft == 0) {
|
|
_isTrollAway = true;
|
|
} else { // make odd 1:3
|
|
_isTrollAway = (rnd(3) != 2);
|
|
}
|
|
break;
|
|
case OT_GET:
|
|
if (!_isTrollAway) {
|
|
printUserMessage(34);
|
|
} else {
|
|
for (int i = 0; i < 4; i++) {
|
|
playTune(1, 3);
|
|
// delayMillis()
|
|
}
|
|
|
|
_roomStates[_currentRoom] = 1;
|
|
_roomPicDeltas[_currentRoom] = 0;
|
|
|
|
_roomPicture++;
|
|
|
|
if (_roomConnects[roomParam - 1] != 0xff) {
|
|
_roomStates[_roomConnects[roomParam - 1]] = 1;
|
|
}
|
|
|
|
if (roomParam == 1)
|
|
haveFlashlight = true;
|
|
|
|
_locMessagesIdx[_currentRoom] = IDO_TRO_LOCMESSAGES +
|
|
(roomParam + 42) * 39;
|
|
|
|
pickupTreasure(roomParam);
|
|
}
|
|
break;
|
|
case OT_DO:
|
|
if (roomParam != 16) {
|
|
printUserMessage(roomParam);
|
|
break;
|
|
}
|
|
|
|
done = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void TrollEngine::fillOffsets() {
|
|
int i;
|
|
|
|
for (i = 0; i < IDI_TRO_PICNUM; i++)
|
|
_pictureOffsets[i] = READ_LE_UINT16(_gameData + IDO_TRO_PIC_START + i * 2);
|
|
|
|
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++) {
|
|
_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;
|
|
|
|
int start = READ_LE_UINT16(_gameData + IDO_TRO_ROOMDESCS);
|
|
int ptr;
|
|
int j;
|
|
|
|
for (i = 0; i < IDI_TRO_NUM_ROOMDESCS; i++, start += 2) {
|
|
ptr = READ_LE_UINT16(_gameData + start);
|
|
|
|
for (j = 0; j < 3; j++)
|
|
_roomDescs[i].options[j] = _gameData[ptr++];
|
|
|
|
for (j = 0; j < 3; j++) {
|
|
switch (_gameData[ptr++]) {
|
|
case 0:
|
|
_roomDescs[i].optionTypes[j] = OT_GO;
|
|
break;
|
|
case 1:
|
|
_roomDescs[i].optionTypes[j] = OT_GET;
|
|
break;
|
|
case 2:
|
|
_roomDescs[i].optionTypes[j] = OT_DO;
|
|
break;
|
|
case 3:
|
|
_roomDescs[i].optionTypes[j] = OT_FLASHLIGHT;
|
|
break;
|
|
default:
|
|
error("Bad data @ (%x) %d", ptr - 1, i);
|
|
}
|
|
}
|
|
|
|
for (j = 0; j < 3; j++)
|
|
_roomDescs[i].roomDescIndex[j] = _gameData[ptr++];
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
for (i = 0; i < IDO_TRO_NONTROLLROOMS; i++)
|
|
_nonTrollRooms[i] = _gameData[IDO_TRO_NONTROLLROOMS + i];
|
|
|
|
_tunes[0] = 0x3BFD;
|
|
_tunes[1] = 0x3C09;
|
|
_tunes[2] = 0x3C0D;
|
|
_tunes[3] = 0x3C11;
|
|
_tunes[4] = 0x3C79;
|
|
_tunes[5] = 0x3CA5;
|
|
}
|
|
|
|
// Init
|
|
|
|
void TrollEngine::init() {
|
|
_picture->setPictureVersion(AGIPIC_V15);
|
|
//SetScreenPar(320, 200, (char *)ibm_fontdata);
|
|
|
|
const int gaps[] = { 0x3A40, 0x4600, 0x4800, 0x5800, 0x5a00, 0x6a00,
|
|
0x6c00, 0x7400, 0x7600, 0x7c00, 0x7e00, 0x8e00,
|
|
0x9000, 0xa000, 0xa200, 0xb200, 0xb400, 0xc400,
|
|
0xc600, 0xd600, 0xd800, 0xe800, 0xea00, 0xfa00,
|
|
0xfc00, 0x10c00, 0x10e00, 0x11e00, 0x12000, 0x13000 };
|
|
|
|
Common::File infile;
|
|
if (!infile.open(IDA_TRO_BINNAME))
|
|
return;
|
|
|
|
_gameData = (byte *)malloc(0xD9C0);
|
|
|
|
bool flip = true;
|
|
byte *ptr = _gameData;
|
|
int diff;
|
|
|
|
for (int i = 0; i < ARRAYSIZE(gaps) - 1; i++) {
|
|
diff = gaps[i + 1] - gaps[i];
|
|
|
|
if (flip) {
|
|
infile.seek(gaps[i]);
|
|
infile.read(ptr, diff);
|
|
ptr += diff;
|
|
} else {
|
|
}
|
|
flip = !flip;
|
|
}
|
|
|
|
// One sector is off
|
|
infile.seek(0x18470);
|
|
infile.read(_gameData + 15632, 592);
|
|
|
|
infile.close();
|
|
|
|
fillOffsets();
|
|
}
|
|
|
|
Common::Error TrollEngine::go() {
|
|
init();
|
|
|
|
while (!shouldQuit()) {
|
|
intro();
|
|
gameLoop();
|
|
gameOver();
|
|
}
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
} // End of namespace Agi
|