WIP for Troll's Tale

svn-id: r28939
This commit is contained in:
Eugene Sandulenko 2007-09-18 16:20:44 +00:00
parent 9b528826f8
commit 13a73a70b6
15 changed files with 913 additions and 121 deletions

View file

@ -103,9 +103,10 @@ enum AgiGameID {
GID_SQ1,
GID_SQ2,
GID_XMASCARD,
GID_FANMADE, // TODO: Should this be extended to include all fanmade games?
GID_FANMADE,
GID_MICKEY, // PreAGI
GID_WINNIE // PreAGI
GID_WINNIE, // PreAGI
GID_TROLL // PreAGI
};
} // End of namespace Agi
@ -930,64 +931,6 @@ public:
char _predictiveResult[40];
};
class PreAgiEngine : public AgiBase {
int _gameId;
protected:
int init();
int go();
void shutdown();
void initialize();
bool initGame();
public:
void agiTimerLow() {}
int agiGetKeypressLow() { return 0; }
int agiIsKeypressLow() { return 0; }
PreAgiEngine(OSystem *syst);
virtual ~PreAgiEngine();
int getGameId() {
return _gameId;
}
GfxMgr *_gfx;
SoundMgr *_sound;
PictureMgr *_picture;
void clearImageStack() {}
void recordImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
int16 p4, int16 p5, int16 p6, int16 p7) {}
void replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
int16 p4, int16 p5, int16 p6, int16 p7) {}
void releaseImageStack() {}
// Game
Common::String getTargetName() { return _targetName; }
// Screen
void clearScreen(int attr);
// Keyboard
int getSelection(int type);
bool waitAnyKeyChoice();
int rnd(int hi) { return (_rnd->getRandomNumber(hi) + 1); }
// Text
void drawStr(int row, int col, int attr, const char *buffer);
void drawStrMiddle(int row, int attr, const char *buffer);
void clearTextArea();
void clearRow(int row);
void XOR80(char *buffer);
void printStr(const char *szMsg);
void printStrXOR(char *szMsg);
// Saved Games
Common::SaveFileManager* getSaveFileMan() { return _saveFileMan; }
};
} // End of namespace Agi
#endif /* AGI_H */

View file

@ -32,6 +32,7 @@
#include "common/file.h"
#include "agi/agi.h"
#include "agi/preagi.h"
#include "agi/wagparser.h"
@ -93,6 +94,7 @@ static const PlainGameDescriptor agiGames[] = {
{"sq2", "Space Quest II: Vohaul's Revenge"},
{"sqx", "Space Quest X: The Lost Chapter"},
{"tetris", "AGI Tetris"},
{"troll", "Troll\'s Tale"},
{"winnie", "Winnie the Pooh in the Hundred Acre Wood"},
{"xmascard", "Xmas Card"},
@ -1614,6 +1616,23 @@ static const AGIGameDescription gameDescriptions[] = {
0x2936,
},
{
// Troll's Tale
// preagi game
{
"troll",
"",
AD_ENTRY1s("troll.exe", "c594b4d6791e9580d8d5dc9d71760027", 59120),
Common::EN_ANY,
Common::kPlatformPC,
Common::ADGF_NO_FLAGS
},
GID_TROLL,
GType_PreAGI,
0,
0x0000,
},
{
// Winnie the Pooh in the Hundred Acre Wood
// preagi game

View file

@ -25,6 +25,7 @@ MODULE_OBJS = \
preagi.o \
preagi_common.o \
preagi_mickey.o \
preagi_troll.o \
preagi_winnie.o \
predictive.o \
saveload.o \

View file

@ -41,7 +41,7 @@ PictureMgr::PictureMgr(AgiBase *agi, GfxMgr *gfx) {
_patCode = _patNum = _priOn = _scrOn = _scrColor = _priColor = 0;
_xOffset = _yOffset = 0;
_pictureType = AGIPIC_V2;
_pictureVersion = AGIPIC_V2;
_minCommand = 0xf0;
_flags = 0;
}
@ -253,6 +253,11 @@ INLINE int PictureMgr::isOkFillHere(int x, int y) {
p = _vm->_game.sbuf16c[y * _width + x];
// FIXME: This overflows stack, but otherwise is a wild guess
// original has some checks against color 11 (0xB)
if (_pictureVersion == AGIPIC_V15 && 0)
return (p & 0x0f) == 0;
if (!_priOn && _scrOn && _scrColor != 15)
return (p & 0x0f) == 15;
@ -322,7 +327,7 @@ void PictureMgr::agiFill(unsigned int x, unsigned int y) {
**
** Draws an xCorner (drawing action 0xF5)
**************************************************************************/
void PictureMgr::xCorner() {
void PictureMgr::xCorner(bool skipOtherCoords) {
int x1, x2, y1, y2;
x1 = nextByte();
@ -332,11 +337,20 @@ void PictureMgr::xCorner() {
for (;;) {
x2 = nextByte();
if (skipOtherCoords)
if (nextByte() >= _minCommand)
break;
if (x2 >= _minCommand)
break;
drawLine(x1, y1, x2, y1);
x1 = x2;
if (skipOtherCoords)
if (nextByte() >= _minCommand)
break;
y2 = nextByte();
if (y2 >= _minCommand)
@ -353,7 +367,7 @@ void PictureMgr::xCorner() {
**
** Draws an yCorner (drawing action 0xF4)
**************************************************************************/
void PictureMgr::yCorner() {
void PictureMgr::yCorner(bool skipOtherCoords) {
int x1, x2, y1, y2;
x1 = nextByte();
@ -361,6 +375,10 @@ void PictureMgr::yCorner() {
putVirtPixel(x1, y1);
for (;;) {
if (skipOtherCoords)
if (nextByte() >= _minCommand)
break;
y2 = nextByte();
if (y2 >= _minCommand)
@ -373,6 +391,10 @@ void PictureMgr::yCorner() {
if (x2 >= _minCommand)
break;
if (skipOtherCoords)
if (nextByte() >= _minCommand)
break;
drawLine(x1, y1, x2, y1);
x1 = x2;
}
@ -388,6 +410,10 @@ void PictureMgr::yCorner() {
void PictureMgr::fill() {
int x1, y1;
if (_pictureVersion == AGIPIC_V15 && 0)
if (_scrColor == 0xf && !(_flags & kPicFTrollMode))
return;
while ((x1 = nextByte()) < _minCommand && (y1 = nextByte()) < _minCommand)
agiFill(x1, y1);
@ -472,7 +498,7 @@ void PictureMgr::plotPattern(int x, int y) {
int counterStep;
int ditherCond;
if (_flags == kPicFCircle)
if (_flags & kPicFCircle)
_patCode |= 0x10;
if (_vm->getGameType() == GType_PreAGI) {
@ -555,7 +581,7 @@ void PictureMgr::drawPicture() {
for (drawing = 1; drawing && _foffs < _flen;) {
act = nextByte();
if (_pictureType == AGIPIC_C64 && act >= 0xf0 && act <= 0xfe) {
if (_pictureVersion == AGIPIC_C64 && act >= 0xf0 && act <= 0xfe) {
_scrColor = act - 0xf0;
continue;
}
@ -586,30 +612,37 @@ void PictureMgr::drawPicture() {
plotBrush();
break;
case 0xf0: // set colour on screen (AGI pic v2)
if (_pictureVersion == AGIPIC_V15)
break;
_scrColor = nextByte();
_scrColor &= 0xF; // for v3 drawing diff
_scrOn = true;
break;
case 0xf1:
if (_pictureType == AGIPIC_V1) {
if (_pictureVersion == AGIPIC_V1) {
_scrColor = nextByte();
_scrColor &= 0xF; // for v3 drawing diff
_scrOn = true;
_priOn = false;
} else if (_pictureType == AGIPIC_V15) { // set colour on screen
} else if (_pictureVersion == AGIPIC_V15) { // set colour on screen
_scrColor = nextByte();
_scrColor &= 0xF;
} else if (_pictureType == AGIPIC_V2) { // disable screen drawing
_scrOn = true;
} else if (_pictureVersion == AGIPIC_V2) { // disable screen drawing
_scrOn = false;
}
break;
case 0xf2: // set colour on priority (AGI pic v2)
if (_pictureVersion == AGIPIC_V15)
break;
_priColor = nextByte();
_priColor &= 0xf; // for v3 drawing diff
_priOn = true;
break;
case 0xf3:
if (_pictureType == AGIPIC_V1) {
if (_pictureVersion == AGIPIC_V1) {
_scrColor = nextByte();
_scrColor &= 0xF; // for v3 drawing diff
_scrOn = true;
@ -618,34 +651,47 @@ void PictureMgr::drawPicture() {
_priOn = true;
}
// Empty in AGI pic V1.5
if (_pictureVersion == AGIPIC_V15 && (_flags & kPicFf3Stop))
drawing = 0;
if (_pictureType == AGIPIC_V2) // disable priority screen
if (_pictureVersion == AGIPIC_V2) // disable priority screen
_priOn = false;
break;
case 0xf4: // y-corner
if (_pictureVersion == AGIPIC_V15)
break;
yCorner();
break;
case 0xf5: // x-corner
if (_pictureVersion == AGIPIC_V15)
break;
xCorner();
break;
case 0xf6: // absolute draw lines
if (_pictureVersion == AGIPIC_V15)
break;
absoluteDrawLine();
break;
case 0xf7: // dynamic draw lines
if (_pictureVersion == AGIPIC_V15)
break;
dynamicDrawLine();
break;
case 0xf8: // fill
if (_pictureType == AGIPIC_V15) {
absoluteDrawLine();
} else if (_pictureType == AGIPIC_V2) {
if (_pictureVersion == AGIPIC_V15) {
yCorner(true);
} else if (_pictureVersion == AGIPIC_V2) {
fill();
}
break;
case 0xf9: // set pattern
if (_pictureType == AGIPIC_V15) {
absoluteDrawLine();
} else if (_pictureType == AGIPIC_V2) {
if (_pictureVersion == AGIPIC_V15) {
xCorner(true);
} else if (_pictureVersion == AGIPIC_V2) {
_patCode = nextByte();
if (_vm->getGameType() == GType_PreAGI)
@ -653,26 +699,29 @@ void PictureMgr::drawPicture() {
}
break;
case 0xfa: // plot brush
if (_pictureType == AGIPIC_V1) {
if (_pictureVersion == AGIPIC_V1) {
_scrOn = false;
_priOn = true;
absoluteDrawLine();
_scrOn = true;
_priOn = false;
} else if (_pictureType == AGIPIC_V15) {
} else if (_pictureVersion == AGIPIC_V15) {
absoluteDrawLine();
} else if (_pictureType == AGIPIC_V2) {
} else if (_pictureVersion == AGIPIC_V2) {
plotBrush();
}
break;
case 0xfb:
if (_pictureType == AGIPIC_V1) {
if (_pictureVersion == AGIPIC_V1) {
dynamicDrawLine();
} else if (_pictureType == AGIPIC_V15) {
} else if (_pictureVersion == AGIPIC_V15) {
absoluteDrawLine();
}
break;
case 0xfc: // fill (AGI pic v1)
if (_pictureVersion == AGIPIC_V15)
break;
_scrColor = nextByte();
_scrColor &= 0xF;
_priColor = nextByte();
@ -689,9 +738,9 @@ void PictureMgr::drawPicture() {
drawing = 0;
break;
default:
warning("Unknown v2 picture opcode (%x)", act);
warning("Unknown picture opcode (%x) at (%x)", act, _foffs - 1);
}
if (_flags == kPicFStep && _vm->getGameType() == GType_PreAGI) {
if ((_flags & kPicFStep) && _vm->getGameType() == GType_PreAGI) {
// FIXME: This is used by Mickey for the crystal animation, but
// currently it's very very very slow
/*
@ -879,10 +928,10 @@ void PictureMgr::setPattern(uint8 code, uint8 num) {
_patNum = num;
}
void PictureMgr::setPictureType(int type) {
_pictureType = type;
void PictureMgr::setPictureVersion(AgiPictureVersion version) {
_pictureVersion = version;
if (type == AGIPIC_C64)
if (version == AGIPIC_C64)
_minCommand = 0xe0;
else
_minCommand = 0xf0;

View file

@ -50,9 +50,12 @@ enum AgiPictureVersion {
};
enum AgiPictureFlags {
kPicFNone,
kPicFCircle,
kPicFStep
kPicFNone = (1 >> 0),
kPicFCircle = (1 >> 1),
kPicFStep = (1 >> 2),
kPicFf3Stop = (1 >> 3),
kPicFf3Cont = (1 >> 4),
kPicFTrollMode = (1 >> 5)
};
class AgiBase;
@ -71,8 +74,8 @@ private:
INLINE int isOkFillHere(int x, int y);
void fillScanline(int x, int y);
void agiFill(unsigned int x, unsigned int y);
void xCorner();
void yCorner();
void xCorner(bool skipOtherCoords = false);
void yCorner(bool skipOtherCoords = false);
void fill();
int plotPatternPoint(int x, int y, int bitpos);
void plotBrush();
@ -93,7 +96,7 @@ public:
void setPattern(uint8 code, uint8 num);
void setPictureType(int type);
void setPictureVersion(AgiPictureVersion version);
void setPictureData(uint8 *data, int len);
void setPictureFlags(int flags) { _flags = flags; }
@ -103,6 +106,11 @@ public:
_yOffset = offY;
}
void setDimensions(int w, int h) {
_width = w;
_height = h;
}
void putPixel(int x, int y, uint8 color) {
_scrColor = color;
_priOn = false;
@ -124,7 +132,7 @@ private:
uint8 _minCommand;
int _pictureType;
AgiPictureVersion _pictureVersion;
int _width, _height;
int _xOffset, _yOffset;

View file

@ -38,7 +38,7 @@
#include "sound/mididrv.h"
#include "sound/mixer.h"
#include "agi/agi.h"
#include "agi/preagi.h"
#include "agi/graphics.h"
#include "agi/sprite.h"
#include "agi/opcodes.h"
@ -48,6 +48,7 @@
// preagi engines
#include "agi/preagi_mickey.h"
#include "agi/preagi_troll.h"
#include "agi/preagi_winnie.h"
namespace Agi {
@ -161,6 +162,8 @@ void PreAgiEngine::initialize() {
_game.colorFg = 15;
_game.colorBg = 0;
_defaultColor = 0xF;
_game.name[0] = '\0';
_game.sbufOrig = (uint8 *)calloc(_WIDTH, _HEIGHT * 2); // Allocate space for two AGI screens vertically
@ -233,6 +236,13 @@ int PreAgiEngine::go() {
winnie->run();
}
break;
case GID_TROLL:
{
Troll *troll = new Troll(this);
troll->init();
troll->run();
}
break;
default:
error("Unknown preagi engine");
break;

98
engines/agi/preagi.h Normal file
View file

@ -0,0 +1,98 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#ifndef AGI_PREAGI_H
#define AGI_PREAGI_H
#include "agi/agi.h"
#include "agi/preagi_common.h"
namespace Agi {
class PreAgiEngine : public AgiBase {
int _gameId;
protected:
int init();
int go();
void shutdown();
void initialize();
bool initGame();
public:
void agiTimerLow() {}
int agiGetKeypressLow() { return 0; }
int agiIsKeypressLow() { return 0; }
PreAgiEngine(OSystem *syst);
virtual ~PreAgiEngine();
int getGameId() {
return _gameId;
}
GfxMgr *_gfx;
SoundMgr *_sound;
PictureMgr *_picture;
void clearImageStack() {}
void recordImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
int16 p4, int16 p5, int16 p6, int16 p7) {}
void replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
int16 p4, int16 p5, int16 p6, int16 p7) {}
void releaseImageStack() {}
// Game
Common::String getTargetName() { return _targetName; }
// Screen
void clearScreen(int attr);
void clearGfxScreen(int attr);
// Keyboard
int getSelection(SelectionTypes type);
bool waitAnyKeyChoice();
int rnd(int hi) { return (_rnd->getRandomNumber(hi) + 1); }
// Text
void drawStr(int row, int col, int attr, const char *buffer);
void drawStrMiddle(int row, int attr, const char *buffer);
void clearTextArea();
void clearRow(int row);
void XOR80(char *buffer);
void printStr(const char *szMsg);
void printStrXOR(char *szMsg);
// Saved Games
Common::SaveFileManager* getSaveFileMan() { return _saveFileMan; }
private:
int _defaultColor;
};
} // End of namespace Agi
#endif

View file

@ -26,32 +26,34 @@
#include "common/stdafx.h"
#include "common/events.h"
#include "agi/agi.h"
#include "agi/preagi.h"
#include "agi/font.h"
#include "agi/graphics.h"
#include "agi/keyboard.h"
// preagi engines
#include "agi/preagi_mickey.h"
// default attributes
#define IDA_DEFAULT 0x0F
#define IDA_DEFAULT_REV 0xF0
#define IDI_MAX_ROW_PIC 20
#include "agi/preagi_common.h"
namespace Agi {
// Screen functions
void PreAgiEngine::clearScreen(int attr) {
void PreAgiEngine::clearScreen(int attr) {
_defaultColor = attr;
_gfx->clearScreen((attr & 0xF0) / 0x10);
}
void PreAgiEngine::clearGfxScreen(int attr) {
_gfx->drawRectangle(0, 0, GFX_WIDTH - 1, IDI_MAX_ROW_PIC * 8 -1, (attr & 0xF0) / 0x10);
}
// String functions
void PreAgiEngine::drawStr(int row, int col, int attr, const char *buffer) {
int code;
if (attr == kColorDefault)
attr = _defaultColor;
for (int iChar = 0; iChar < (int)strlen(buffer); iChar++) {
code = buffer[iChar];
@ -112,7 +114,7 @@ void PreAgiEngine::printStrXOR(char *szMsg) {
// Input functions
int PreAgiEngine::getSelection(int type) {
int PreAgiEngine::getSelection(SelectionTypes type) {
Common::Event event;
// Selection types:
@ -131,13 +133,13 @@ int PreAgiEngine::getSelection(int type) {
case Common::EVENT_KEYDOWN:
switch (event.kbd.keycode) {
case Common::KEYCODE_y:
if (type == 0)
if (type == kSelYesNo)
return 1;
case Common::KEYCODE_n:
if (type == 0)
if (type == kSelYesNo)
return 0;
case Common::KEYCODE_ESCAPE:
if (type == 1)
if (type == kSelNumber)
return 0;
case Common::KEYCODE_1:
case Common::KEYCODE_2:
@ -148,10 +150,13 @@ int PreAgiEngine::getSelection(int type) {
case Common::KEYCODE_7:
case Common::KEYCODE_8:
case Common::KEYCODE_9:
if (type == 1)
if (type == kSelNumber)
return event.kbd.keycode - Common::KEYCODE_1 + 1;
case Common::KEYCODE_SPACE:
if (type == kSelSpace)
return 1;
default:
if (type == 0) {
if (type == kSelYesNo) {
return 2;
} else {
return 10;
@ -162,6 +167,8 @@ int PreAgiEngine::getSelection(int type) {
break;
}
}
_system->updateScreen();
_system->delayMillis(10);
}
return 0;
}
@ -190,6 +197,8 @@ bool PreAgiEngine::waitAnyKeyChoice() {
break;
}
}
_system->updateScreen();
_system->delayMillis(10);
}
}

View file

@ -0,0 +1,49 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#ifndef AGI_PREAGI_COMMON_H
#define AGI_PREAGI_COMMON_H
namespace Agi {
// default attributes
#define IDA_DEFAULT 0x0F
#define IDA_DEFAULT_REV 0xF0
#define kColorDefault 0x1337
#define IDI_MAX_ROW_PIC 20
enum SelectionTypes {
kSelYesNo,
kSelNumber,
kSelSpace
};
} // End of namespace Agi
#endif

View file

@ -29,13 +29,11 @@
#include "graphics/cursorman.h"
#include "agi/preagi.h"
#include "agi/preagi_common.h"
#include "agi/preagi_mickey.h"
#include "agi/graphics.h"
// default attributes
#define IDA_DEFAULT 0x0F
#define IDA_DEFAULT_REV 0xF0
#define IDI_SND_OSCILLATOR_FREQUENCY 1193180
namespace Agi {
@ -161,7 +159,7 @@ bool Mickey::chooseY_N(int ofsPrompt, bool fErrorMsg) {
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
int a = _vm->getSelection(0);
int a = _vm->getSelection(kSelYesNo);
for (;;) {
switch (a) {
case 0: return false;
@ -173,7 +171,7 @@ bool Mickey::chooseY_N(int ofsPrompt, bool fErrorMsg) {
}
break;
}
a = _vm->getSelection(0);
a = _vm->getSelection(kSelYesNo);
}
}
@ -183,7 +181,7 @@ int Mickey::choose1to9(int ofsPrompt) {
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
int a = _vm->getSelection(1);
int a = _vm->getSelection(kSelNumber);
for (;;) {
if (a == 10) {
printExeStr(IDO_MSA_PRESS_1_TO_9);
@ -191,7 +189,7 @@ int Mickey::choose1to9(int ofsPrompt) {
return 0;
printExeStr(ofsPrompt);
} else return a;
a = _vm->getSelection(1);
a = _vm->getSelection(kSelNumber);
}
}

View file

@ -23,6 +23,9 @@
*
*/
#ifndef AGI_PREAGI_MICKEY_H
#define AGI_PREAGI_MICKEY_H
#include "agi/agi.h"
namespace Agi {
@ -801,4 +804,6 @@ protected:
void waitAnyKey(bool anim = false);
};
}
} // End of namespace Agi
#endif

View file

@ -0,0 +1,429 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "agi/preagi.h"
#include "agi/preagi_common.h"
#include "agi/preagi_troll.h"
#include "agi/graphics.h"
#include "graphics/cursorman.h"
#include "common/events.h"
namespace Agi {
Troll::Troll(PreAgiEngine* vm) : _vm(vm) {
}
// User Interface
void Troll::pressAnyKey() {
_vm->drawStr(24, 4, kColorDefault, IDS_TRO_PRESSANYKEY);
_vm->_gfx->doUpdate();
_vm->waitAnyKeyChoice();
}
void Troll::drawMenu(const char *szMenu, int iSel) {
_vm->clearTextArea();
_vm->drawStr(20, 0, kColorDefault, szMenu);
_vm->drawStr(21 + iSel, 0, kColorDefault, " *");
_vm->_gfx->doUpdate();
}
void Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) {
Common::Event event;
int y;
drawMenu(szMenu, *iSel);
for (;;) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch(event.type) {
case Common::EVENT_QUIT:
_vm->_system->quit();
case Common::EVENT_MOUSEMOVE:
y = event.mouse.y / 8;
if (nSel > y - 21)
*iSel = y - 21;
drawMenu(szMenu, *iSel);
break;
case Common::EVENT_LBUTTONUP:
return;
case Common::EVENT_KEYDOWN:
switch (event.kbd.keycode) {
case Common::KEYCODE_t:
case Common::KEYCODE_f:
inventory();
*iSel = 0;
drawMenu(szMenu, *iSel);
break;
case Common::KEYCODE_SPACE:
*iSel += 1;
if (*iSel == nSel)
*iSel = IDI_TRO_SEL_OPTION_1;
drawMenu(szMenu, *iSel);
break;
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER:
return;
default:
break;
}
break;
default:
break;
}
}
_vm->_system->updateScreen();
_vm->_system->delayMillis(10);
}
}
// Graphics
void Troll::drawPic(int iPic, bool f3IsCont, bool clear) {
uint8 frame[] = {
0xf1, 0x3, 0xf9, 0x0, 0x0, 0x9f, 0x0, 0x9f, 0xa7, 0x0, 0xa7, 0x0, 0x0, 0xff
};
if (clear)
_vm->clearScreen(0x0f);
_vm->_picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT);
_vm->_picture->setPictureData(frame, ARRAYSIZE(frame));
_vm->_picture->drawPicture();
_vm->_picture->setPictureData(_gameData + _pictureOffsets[iPic], 4096);
if (f3IsCont)
_vm->_picture->setPictureFlags(kPicFf3Cont);
else
_vm->_picture->setPictureFlags(kPicFf3Stop);
_vm->_picture->drawPicture();
_vm->_picture->showPic();
_vm->_gfx->doUpdate();
}
// Game Logic
void Troll::inventory() {
char szMissing[40];
_vm->clearScreen(0x07);
_vm->drawStr(1, 12, kColorDefault, IDS_TRO_TREASURE_0);
_vm->drawStr(2, 12, kColorDefault, IDS_TRO_TREASURE_1);
switch (_treasuresLeft) {
case 1:
sprintf(szMissing, IDS_TRO_TREASURE_5, _treasuresLeft);
_vm->drawStr(20, 10,kColorDefault, szMissing);
break;
case 0:
_vm->drawStr(20, 1, kColorDefault, IDS_TRO_TREASURE_6);
break;
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);
break;
}
_vm->drawStr(24, 6, kColorDefault, IDS_TRO_PRESSANYKEY);
_vm->_gfx->doUpdate();
_vm->waitAnyKeyChoice();
}
void Troll::waitAnyKeyIntro() {
Common::Event event;
int iMsg = 0;
for (;;) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch(event.type) {
case Common::EVENT_QUIT:
_vm->_system->quit();
case Common::EVENT_LBUTTONUP:
case Common::EVENT_KEYDOWN:
return;
default:
break;
}
}
switch (iMsg) {
case 200:
iMsg = 0;
case 0:
_vm->drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_2);
_vm->_gfx->doUpdate();
break;
case 100:
_vm->drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_3);
_vm->_gfx->doUpdate();
break;
}
iMsg++;
_vm->_system->updateScreen();
_vm->_system->delayMillis(10);
}
}
void Troll::credits() {
_vm->clearScreen(0x07);
_vm->drawStr(1, 2, kColorDefault, IDS_TRO_CREDITS_0);
_vm->drawStr(7, 19, 10, "T");
_vm->drawStr(7, 20, 11, "R");
_vm->drawStr(7, 21, 12, "O");
_vm->drawStr(7, 22, 13, "L");
_vm->drawStr(7, 23, 14, "L");
_vm->drawStr(7, 24, 15, "'");
_vm->drawStr(7, 25, 9, "S");
_vm->drawStr(7, 27, 11, "T");
_vm->drawStr(7, 28, 12, "A");
_vm->drawStr(7, 29, 13, "L");
_vm->drawStr(7, 30, 14, "E");
_vm->drawStr(7, 32, 9, "(");
_vm->drawStr(7, 33, 10, "t");
_vm->drawStr(7, 34, 11, "m");
_vm->drawStr(7, 35, 12, ")");
_vm->drawStr(8, 19, kColorDefault, IDS_TRO_CREDITS_2);
_vm->drawStr(13, 11, 9, IDS_TRO_CREDITS_3);
_vm->drawStr(15, 8, 10, IDS_TRO_CREDITS_4);
_vm->drawStr(17, 7, 12, IDS_TRO_CREDITS_5);
_vm->drawStr(19, 2, 14, IDS_TRO_CREDITS_6);
_vm->_gfx->doUpdate();
pressAnyKey();
}
void Troll::tutorial() {
bool done = false;
int iSel = 0;
//char szTreasure[16] = {0};
for (;;) {
//SetGfxMode();
_vm->printStr(IDS_TRO_TUTORIAL_0);
_vm->getSelection(kSelSpace);
done = false;
while (!done) {
getMenuSel(IDS_TRO_TUTORIAL_1, &iSel, IDI_TRO_MAX_OPTION);
switch(iSel) {
case IDI_TRO_SEL_OPTION_1:
_vm->clearGfxScreen(0x0B);
_vm->_gfx->doUpdate();
break;
case IDI_TRO_SEL_OPTION_2:
_vm->clearGfxScreen(0x00);
_vm->_gfx->doUpdate();
break;
case IDI_TRO_SEL_OPTION_3:
done = true;
break;
}
}
// do you need more practice ?
_vm->clearScreen(0x4F);
_vm->drawStr(7, 4, kColorDefault, IDS_TRO_TUTORIAL_5);
_vm->drawStr(9, 4, kColorDefault, IDS_TRO_TUTORIAL_6);
_vm->_gfx->doUpdate();
if (!_vm->getSelection(kSelYesNo))
break;
}
// show info texts
_vm->clearScreen(0x5F);
_vm->drawStr(4, 1, kColorDefault, IDS_TRO_TUTORIAL_7);
_vm->drawStr(5, 1, kColorDefault, IDS_TRO_TUTORIAL_8);
_vm->_gfx->doUpdate();
pressAnyKey();
_vm->clearScreen(0x2F);
_vm->drawStr(6, 1, kColorDefault, IDS_TRO_TUTORIAL_9);
_vm->_gfx->doUpdate();
pressAnyKey();
_vm->clearScreen(0x19);
_vm->drawStr(7, 1, kColorDefault, IDS_TRO_TUTORIAL_10);
_vm->drawStr(8, 1, kColorDefault, IDS_TRO_TUTORIAL_11);
_vm->_gfx->doUpdate();
pressAnyKey();
_vm->clearScreen(0x6E);
_vm->drawStr(9, 1, kColorDefault, IDS_TRO_TUTORIAL_12);
_vm->drawStr(10, 1, kColorDefault, IDS_TRO_TUTORIAL_13);
_vm->_gfx->doUpdate();
pressAnyKey();
_vm->clearScreen(0x4C);
_vm->drawStr(11, 1, kColorDefault, IDS_TRO_TUTORIAL_14);
_vm->drawStr(12, 1, kColorDefault, IDS_TRO_TUTORIAL_15);
_vm->_gfx->doUpdate();
pressAnyKey();
_vm->clearScreen(0x5D);
_vm->drawStr(13, 1, kColorDefault, IDS_TRO_TUTORIAL_16);
_vm->drawStr(14, 1, kColorDefault, IDS_TRO_TUTORIAL_17);
_vm->drawStr(15, 1, kColorDefault, IDS_TRO_TUTORIAL_18);
_vm->_gfx->doUpdate();
pressAnyKey();
// show treasures
_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->_gfx->doUpdate();
pressAnyKey();
}
void Troll::intro() {
// sierra on-line presents
_vm->clearScreen(0x2F);
_vm->drawStr(9, 10, kColorDefault, IDS_TRO_INTRO_0);
_vm->drawStr(14, 15, kColorDefault, IDS_TRO_INTRO_1);
_vm->_gfx->doUpdate();
_vm->_system->updateScreen();
// draw troll picture
_vm->_system->delayMillis(320);
// Draw logo
drawPic(45, false, true);
_vm->_gfx->doUpdate();
// wait for keypress and alternate message
waitAnyKeyIntro();
// have you played this game before?
_vm->drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_4);
_vm->drawStr(23, 6, kColorDefault, IDS_TRO_INTRO_5);
_vm->_gfx->doUpdate();
if (!_vm->getSelection(kSelYesNo))
tutorial();
credits();
}
void Troll::gameOver() {
char szMoves[40];
_vm->clearScreen(0x0f); // hack
_vm->clearTextArea();
//DrawPic(0);
_vm->clearTextArea();
//DrawPic(0);
sprintf(szMoves, IDS_TRO_GAMEOVER_0, _moves);
_vm->drawStr(21, 1, kColorDefault, szMoves);
_vm->drawStr(22, 1, kColorDefault, IDS_TRO_GAMEOVER_1);
_vm->_gfx->doUpdate();
pressAnyKey();
}
void Troll::gameLoop() {
int iSel;
//int nSel;
bool done = false;
//char szMsg[161];
//char szMenu[161];
while (!done) {
// Troll_DrawRoomPic(_currentRoom);
// Troll_ReadRoomText(_currentRoom, szMsg, szMenu, &nSel);
iSel = 0;
//getMenuSel(szMsg, szMenu, &iSel, nSel);
_moves++;
switch(iSel) {
case IDI_TRO_SEL_OPTION_1:
break;
case IDI_TRO_SEL_OPTION_2:
break;
case IDI_TRO_SEL_OPTION_3:
break;
}
}
}
void Troll::fillPicOffsets() {
for (int i = 0; i < IDI_TRO_PICNUM; i++)
_pictureOffsets[i] = READ_LE_UINT16(_gameData + IDO_TRO_PIC_START + i * 2)
+ IDO_TRO_DATA_START;
}
// Init
void Troll::init() {
_moves = 0;
_currentRoom = 1;
_treasuresLeft = IDI_TRO_MAX_TREASURE;
_vm->_picture->setPictureVersion(AGIPIC_V15);
//SetScreenPar(320, 200, (char*)ibm_fontdata);
Common::File infile;
if (!infile.open(IDA_TRO_BINNAME))
return;
_gameData = (byte *)malloc(infile.size());
infile.read(_gameData, infile.size());
infile.close();
fillPicOffsets();
}
void Troll::run() {
intro();
//gameLoop();
gameOver();
}
} // end of namespace Agi

167
engines/agi/preagi_troll.h Normal file
View file

@ -0,0 +1,167 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#ifndef AGI_PREAGI_TROLL_H
#define AGI_PREAGI_TROLL_H
#include "agi/agi.h"
namespace Agi {
// strings
#define IDS_TRO_DISK "ERROR ERROR !"
#define IDS_TRO_PATH_PIC "%s"
#define IDS_TRO_PRESSANYKEY "PRESS ANY KEY TO CONTINUE:"
#define IDS_TRO_INTRO_0 "SIERRA ON-LINE INC."
#define IDS_TRO_INTRO_1 "Presents :"
#define IDS_TRO_INTRO_2 "Copyright 1984 Sierra On-Line Inc."
#define IDS_TRO_INTRO_3 " Press any key to continue. "
#define IDS_TRO_INTRO_4 "HAVE YOU PLAYED THIS GAME BEFORE ?"
#define IDS_TRO_INTRO_5 "PRESS <Y> OR <N>"
#define IDS_TRO_TUTORIAL_0 " First press the <space bar>.\n 1. Turn the screen GREEN.\n 2. Turn the screen BLACK.\n *3. SEE a SURPRISE, and then more."
#define IDS_TRO_TUTORIAL_1 " Press <return> to make your choice.\n 1. Turn the screen GREEN.\n 2. Turn the screen BLACK.\n 3. SEE a SURPRISE, and then more."
//#define IDS_TRO_TUTORIAL_0 "First press the <space bar>."
//#define IDS_TRO_TUTORIAL_1 "1. Turn the screen GREEN."
//#define IDS_TRO_TUTORIAL_2 "2. Turn the screen BLACK."
//#define IDS_TRO_TUTORIAL_3 "3. SEE a SURPRISE, and then more."
//#define IDS_TRO_TUTORIAL_4 "Press <return> to make your choice."
#define IDS_TRO_TUTORIAL_5 "Would you like more practice ?"
#define IDS_TRO_TUTORIAL_6 "Press <Y> for yes, <N> for no."
#define IDS_TRO_TUTORIAL_7 "The evil TROLL has hidden all the"
#define IDS_TRO_TUTORIAL_8 "Treasures of MARK, the Dwarf King."
#define IDS_TRO_TUTORIAL_9 "Help KING MARK find his Treasures."
#define IDS_TRO_TUTORIAL_10 "You can't take a Treasure if the TROLL"
#define IDS_TRO_TUTORIAL_11 "is in the same picture as the Treasure."
#define IDS_TRO_TUTORIAL_12 "To make the TROLL go away you have to"
#define IDS_TRO_TUTORIAL_13 "make the picture change."
#define IDS_TRO_TUTORIAL_14 "During the game see the Treasures you"
#define IDS_TRO_TUTORIAL_15 "have already found by pressing <F>."
#define IDS_TRO_TUTORIAL_16 "During the game you can turn the sound"
#define IDS_TRO_TUTORIAL_17 "on or off by pressing the <S> key "
#define IDS_TRO_TUTORIAL_18 "while holding down the <Ctrl> key."
#define IDS_TRO_TUTORIAL_19 "The TROLL has hidden these Treasures:"
#define IDS_TRO_CREDITS_0 "Prepare to enter the world of . . ."
#define IDS_TRO_CREDITS_1 "TROLL'S TALE (tm)"
#define IDS_TRO_CREDITS_2 "------------"
#define IDS_TRO_CREDITS_3 "Written by MIKE MACCHESNEY"
#define IDS_TRO_CREDITS_4 "Conversion by PETER OLIPHANT"
#define IDS_TRO_CREDITS_5 "Graphic Art by DOUG MACNEILL"
#define IDS_TRO_CREDITS_6 "Original Version by AL LOWE"
#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_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!!"
#define IDS_TRO_TREASURE_7 "THERE'S ONLY ONE MORE TREASURE TO FIND."
#define IDS_TRO_TREASURE_8 "GREAT!! YOU HAVE FOUND EVERY TREASURE."
#define IDS_TRO_TREASURE_9 "TAKE THE TREASURES TO THE GUARD."
#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
#define IDI_TRO_PIC_WIDTH 160
#define IDI_TRO_PIC_HEIGHT 168
#define IDI_TRO_PIC_X0 0
#define IDI_TRO_PIC_Y0 0
#define IDI_TRO_PIC_FLAGS IDF_AGI_PIC_V15
// max values
#define IDI_TRO_MAX_TREASURE 16
#define IDI_TRO_MAX_OPTION 3
#define IDI_TRO_SEL_OPTION_1 0
#define IDI_TRO_SEL_OPTION_2 1
#define IDI_TRO_SEL_OPTION_3 2
// offsets
#define IDA_TRO_BINNAME "troll.exe"
#define IDO_TRO_DATA_START (0x5855-0x3ef5)
#define IDO_TRO_PIC_START 0x5855
class Troll {
friend class PreAgiEngine;
public:
Troll(PreAgiEngine *vm);
//~Winnie();
void init();
void run();
private:
int _currentRoom;
int _moves;
int _treasuresLeft;
byte *_gameData;
PreAgiEngine *_vm;
void intro();
void drawPic(int iPic, bool f3IsCont, bool clear);
void gameLoop();
void gameOver();
void tutorial();
void credits();
void inventory();
void pressAnyKey();
void waitAnyKeyIntro();
void getMenuSel(const char*, int*, int);
void drawMenu(const char *szMenu, int iSel);
void fillPicOffsets();
private:
int _pictureOffsets[IDI_TRO_PICNUM];
};
} // End of namespace Agi
#endif

View file

@ -23,6 +23,7 @@
*
*/
#include "agi/preagi.h"
#include "agi/preagi_winnie.h"
#include "agi/graphics.h"

View file

@ -23,6 +23,9 @@
*
*/
#ifndef AGI_PREAGI_WINNIE_H
#define AGI_PREAGI_WINNIE_H
#include "agi/agi.h"
namespace Agi {
@ -343,4 +346,7 @@ private:
void showOwlHelp();
};
}
} // End of namespace Agi
#endif