ILLUSIONS: More work on Duckman
This commit is contained in:
parent
3f15233f78
commit
67366aa04b
37 changed files with 2810 additions and 202 deletions
|
@ -226,7 +226,7 @@ void Control::pause() {
|
|||
_vm->_dict->setObjectControl(_objectId, 0);
|
||||
|
||||
if (_objectId == 0x40004)
|
||||
_vm->_cursor->setControl(0);
|
||||
_vm->setCursorControl(0);
|
||||
|
||||
if (_actor && !(_actor->_flags & 0x0200))
|
||||
_actor->destroySurface();
|
||||
|
@ -238,7 +238,7 @@ void Control::unpause() {
|
|||
_vm->_dict->setObjectControl(_objectId, this);
|
||||
|
||||
if (_objectId == 0x40004)
|
||||
_vm->_cursor->setControl(this);
|
||||
_vm->setCursorControl(this);
|
||||
|
||||
if (_actor && !(_actor->_flags & 0x0200)) {
|
||||
SurfInfo surfInfo;
|
||||
|
@ -254,7 +254,7 @@ void Control::unpause() {
|
|||
|
||||
void Control::appearActor() {
|
||||
if (_objectId == 0x40004) {
|
||||
_vm->_cursor->show();
|
||||
_vm->showCursor();
|
||||
} else {
|
||||
if (_actor->_frameIndex || _actorTypeId == 0x50004)
|
||||
_actor->_flags |= 1;
|
||||
|
@ -270,7 +270,7 @@ void Control::appearActor() {
|
|||
|
||||
void Control::disappearActor() {
|
||||
if (_objectId == 0x40004) {
|
||||
_vm->_cursor->hide();
|
||||
_vm->hideCursor();
|
||||
} else {
|
||||
_actor->_flags &= ~1;
|
||||
_actor->_flags &= ~0x1000;
|
||||
|
@ -540,8 +540,10 @@ void Control::stopActor() {
|
|||
_actor->_pathPointIndex = 0;
|
||||
_actor->_walkCallerThreadId1 = 0;
|
||||
}
|
||||
if (_vm->getGameId() == kGameIdBBDOU) {
|
||||
_vm->notifyThreadId(_actor->_notifyId3C);
|
||||
_vm->notifyThreadId(_actor->_notifyThreadId1);
|
||||
}
|
||||
}
|
||||
|
||||
void Control::startSequenceActor(uint32 sequenceId, int value, uint32 notifyThreadId) {
|
||||
|
@ -623,6 +625,7 @@ void Control::sequenceActor() {
|
|||
appearActor();
|
||||
_actor->_flags &= ~0x1000;
|
||||
}
|
||||
debug(1, "New frame OK");
|
||||
}
|
||||
|
||||
if (sequenceFinished) {
|
||||
|
@ -905,23 +908,44 @@ void Control::startSequenceActorIntern(uint32 sequenceId, int value, byte *entry
|
|||
_actor->_notifyThreadId1 = notifyThreadId;
|
||||
_actor->_notifyId3C = 0;
|
||||
_actor->_walkCallerThreadId1 = 0;
|
||||
_actor->_entryTblPtr = 0;
|
||||
|
||||
Sequence *sequence = _vm->_dict->findSequence(sequenceId);
|
||||
|
||||
if (!sequence && _vm->getGameId() == kGameIdDuckman) {
|
||||
debug("Load external sequence...");
|
||||
_vm->_resSys->loadResource(0x00060000 | (sequenceId & 0xFFFF), _vm->getCurrentScene(), 0);
|
||||
sequence = _vm->_dict->findSequence(sequenceId);
|
||||
_actor->_flags |= 0x800;
|
||||
}
|
||||
|
||||
_actor->_seqCodeIp = sequence->_sequenceCode;
|
||||
_actor->_frames = _vm->_actorItems->findSequenceFrames(sequence);
|
||||
|
||||
_actor->_seqCodeValue3 = 0;
|
||||
_actor->_seqCodeValue1 = 0;
|
||||
|
||||
if (_vm->getGameId() == kGameIdBBDOU) {
|
||||
_actor->_seqCodeValue2 = value == 1 ? 350 : 600;
|
||||
} else if (_vm->getGameId() == kGameIdDuckman) {
|
||||
_actor->_seqCodeValue2 = value == 1 ? 350 : 750;
|
||||
}
|
||||
|
||||
_actor->initSequenceStack();
|
||||
|
||||
if (_vm->getGameId() == kGameIdBBDOU)
|
||||
stopSequenceActor();
|
||||
|
||||
_actor->_linkIndex2 = 0;
|
||||
|
||||
if (entryTblPtr) {
|
||||
_actor->_flags |= 0x80;
|
||||
_actor->_entryTblPtr = entryTblPtr;
|
||||
if (_vm->getGameId() == kGameIdBBDOU) {
|
||||
_actor->_notifyThreadId1 = 0;
|
||||
_actor->_notifyThreadId2 = notifyThreadId;
|
||||
}
|
||||
}
|
||||
|
||||
sequenceActor();
|
||||
|
||||
|
@ -958,7 +982,6 @@ void Controls::placeBackgroundObject(BackgroundObject *backgroundObject) {
|
|||
void Controls::placeActor(uint32 actorTypeId, Common::Point placePt, uint32 sequenceId, uint32 objectId, uint32 notifyThreadId) {
|
||||
Control *control = newControl();
|
||||
Actor *actor = newActor();
|
||||
|
||||
ActorType *actorType = _vm->_dict->findActorType(actorTypeId);
|
||||
|
||||
control->_objectId = objectId;
|
||||
|
@ -967,8 +990,9 @@ void Controls::placeActor(uint32 actorTypeId, Common::Point placePt, uint32 sequ
|
|||
control->readPointsConfig(actorType->_pointsConfig);
|
||||
control->_actorTypeId = actorTypeId;
|
||||
control->_actor = actor;
|
||||
if (actorTypeId == 0x50001 && objectId == 0x40004)
|
||||
actor->setControlRoutine(new Common::Functor2Mem<Control*, uint32, void, Cursor>(_vm->_cursor, &Cursor::cursorControlRoutine));
|
||||
|
||||
if (_vm->isCursorObject(actorTypeId, objectId))
|
||||
_vm->setCursorControlRoutine(control);
|
||||
|
||||
if (actorType->_surfInfo._dimensions._width > 0 || actorType->_surfInfo._dimensions._height > 0) {
|
||||
actor->createSurface(actorType->_surfInfo);
|
||||
|
@ -1015,12 +1039,11 @@ void Controls::placeActor(uint32 actorTypeId, Common::Point placePt, uint32 sequ
|
|||
_controls.push_back(control);
|
||||
_vm->_dict->setObjectControl(objectId, control);
|
||||
|
||||
if (actorTypeId == 0x50001 && objectId == 0x40004)
|
||||
_vm->_cursor->place(control, sequenceId);
|
||||
if (_vm->isCursorObject(actorTypeId, objectId))
|
||||
_vm->placeCursorControl(control, sequenceId);
|
||||
|
||||
control->_flags |= 0x01;
|
||||
actor->_flags |= 0x1000;
|
||||
|
||||
control->startSequenceActor(sequenceId, 2, notifyThreadId);
|
||||
}
|
||||
|
||||
|
@ -1083,6 +1106,25 @@ void Controls::placeSubActor(uint32 objectId, int linkIndex, uint32 actorTypeId,
|
|||
subActor->_linkIndex = linkIndex;
|
||||
}
|
||||
|
||||
void Controls::destroyControls() {
|
||||
ItemsIterator it = _controls.begin();
|
||||
while (it != _controls.end()) {
|
||||
destroyControl(*it);
|
||||
it = _controls.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void Controls::destroyActiveControls() {
|
||||
ItemsIterator it = _controls.begin();
|
||||
while (it != _controls.end()) {
|
||||
if ((*it)->_pauseCtr <= 0) {
|
||||
destroyControl(*it);
|
||||
it = _controls.erase(it);
|
||||
} else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void Controls::destroyControlsByTag(uint32 tag) {
|
||||
ItemsIterator it = _controls.begin();
|
||||
while (it != _controls.end()) {
|
||||
|
@ -1105,6 +1147,24 @@ void Controls::threadIsDead(uint32 threadId) {
|
|||
}
|
||||
}
|
||||
|
||||
void Controls::pauseControls() {
|
||||
for (ItemsIterator it = _controls.begin(); it != _controls.end(); ++it) {
|
||||
Control *control = *it;
|
||||
++control->_pauseCtr;
|
||||
if (control->_pauseCtr == 1)
|
||||
control->pause();
|
||||
}
|
||||
}
|
||||
|
||||
void Controls::unpauseControls() {
|
||||
for (ItemsIterator it = _controls.begin(); it != _controls.end(); ++it) {
|
||||
Control *control = *it;
|
||||
--control->_pauseCtr;
|
||||
if (control->_pauseCtr == 0)
|
||||
control->unpause();
|
||||
}
|
||||
}
|
||||
|
||||
void Controls::pauseControlsByTag(uint32 tag) {
|
||||
for (ItemsIterator it = _controls.begin(); it != _controls.end(); ++it) {
|
||||
Control *control = *it;
|
||||
|
@ -1225,7 +1285,7 @@ void Controls::destroyControl(Control *control) {
|
|||
_vm->_dict->setObjectControl(control->_objectId, 0);
|
||||
|
||||
if (control->_objectId == 0x40004 && control->_pauseCtr <= 0)
|
||||
_vm->_cursor->setControl(0);
|
||||
_vm->setCursorControl(0);
|
||||
|
||||
if (control->_actor) {
|
||||
if (control->_actor->_pathNode && (control->_actor->_flags & 0x400))
|
||||
|
|
|
@ -220,8 +220,12 @@ public:
|
|||
void placeSequenceLessActor(uint32 objectId, Common::Point placePt, WidthHeight dimensions, int16 priority);
|
||||
void placeActorLessObject(uint32 objectId, Common::Point feetPt, Common::Point pt, int16 priority, uint flags);
|
||||
void placeSubActor(uint32 objectId, int linkIndex, uint32 actorTypeId, uint32 sequenceId);
|
||||
void destroyControls();
|
||||
void destroyActiveControls();
|
||||
void destroyControlsByTag(uint32 tag);
|
||||
void threadIsDead(uint32 threadId);
|
||||
void pauseControls();
|
||||
void unpauseControls();
|
||||
void pauseControlsByTag(uint32 tag);
|
||||
void unpauseControlsByTag(uint32 tag);
|
||||
bool getOverlappedObject(Control *control, Common::Point pt, Control **outOverlappedControl, int minPriority);
|
||||
|
|
|
@ -32,7 +32,7 @@ void ActorResourceLoader::load(Resource *resource) {
|
|||
debug("ActorResourceLoader::load() Loading actor %08X from %s...", resource->_resId, resource->_filename.c_str());
|
||||
|
||||
ActorResource *actorResource = new ActorResource();
|
||||
actorResource->load(resource->_data, resource->_dataSize);
|
||||
actorResource->load(resource);
|
||||
resource->_refId = actorResource;
|
||||
|
||||
ActorItem *actorItem = _vm->_actorItems->allocActorItem();
|
||||
|
@ -151,7 +151,10 @@ ActorResource::ActorResource() {
|
|||
ActorResource::~ActorResource() {
|
||||
}
|
||||
|
||||
void ActorResource::load(byte *data, uint32 dataSize) {
|
||||
void ActorResource::load(Resource *resource) {
|
||||
byte *data = resource->_data;
|
||||
uint32 dataSize = resource->_dataSize;
|
||||
|
||||
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
|
||||
|
||||
_totalSize = stream.readUint32LE();
|
||||
|
@ -196,10 +199,14 @@ void ActorResource::load(byte *data, uint32 dataSize) {
|
|||
}
|
||||
|
||||
// Load named points
|
||||
if (resource->_gameId == kGameIdBBDOU) {
|
||||
// The count isn't stored explicitly so calculate it
|
||||
uint namedPointsCount = (actorTypesOffs - 0x20) / 8;
|
||||
stream.seek(0x20);
|
||||
_namedPoints.load(namedPointsCount, stream);
|
||||
}
|
||||
|
||||
debug("ActorResource(%08X) framesCount: %d", resource->_resId, framesCount);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ class ActorResource {
|
|||
public:
|
||||
ActorResource();
|
||||
~ActorResource();
|
||||
void load(byte *data, uint32 dataSize);
|
||||
void load(Resource *resource);
|
||||
bool containsSequence(Sequence *sequence);
|
||||
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
|
||||
public:
|
||||
|
|
|
@ -54,7 +54,11 @@ void BackgroundResourceLoader::load(Resource *resource) {
|
|||
int index = backgroundItem->_bgRes->findMasterBgIndex();
|
||||
_vm->_camera->set(backgroundItem->_bgRes->_bgInfos[index - 1]._panPoint, backgroundItem->_bgRes->_bgInfos[index - 1]._surfInfo._dimensions);
|
||||
|
||||
// NOTE Skipped palette loading (not used in BBDOU)
|
||||
if (backgroundItem->_bgRes->_palettesCount > 0) {
|
||||
Palette *palette = &backgroundItem->_bgRes->_palettes[backgroundItem->_bgRes->_paletteIndex - 1];
|
||||
_vm->_screen->setPalette(palette->_palette, 1, palette->_count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BackgroundResourceLoader::unload(Resource *resource) {
|
||||
|
@ -150,6 +154,15 @@ int ScaleLayer::getScale(Common::Point pos) {
|
|||
return _values[pos.y];
|
||||
}
|
||||
|
||||
// Palette
|
||||
|
||||
void Palette::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_count = stream.readUint16LE();
|
||||
_unk = stream.readUint16LE();
|
||||
uint32 paletteOffs = stream.readUint32LE();
|
||||
_palette = dataStart + paletteOffs;
|
||||
}
|
||||
|
||||
// BackgroundObject
|
||||
|
||||
void BackgroundObject::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
|
@ -176,13 +189,15 @@ void BackgroundResource::load(byte *data, uint32 dataSize) {
|
|||
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
|
||||
// TODO A lot
|
||||
|
||||
stream.seek(8);
|
||||
_paletteIndex = stream.readUint16LE();
|
||||
|
||||
// Load background pixels
|
||||
stream.seek(0x0A);
|
||||
_bgInfosCount = stream.readUint16LE();
|
||||
_bgInfos = new BgInfo[_bgInfosCount];
|
||||
stream.seek(0x20);
|
||||
uint32 bgInfosOffs = stream.readUint32LE();
|
||||
debug("_bgInfosCount: %d", _bgInfosCount);
|
||||
for (uint i = 0; i < _bgInfosCount; ++i) {
|
||||
stream.seek(bgInfosOffs + i * 0x1C);
|
||||
_bgInfos[i].load(data, stream);
|
||||
|
@ -232,6 +247,18 @@ void BackgroundResource::load(byte *data, uint32 dataSize) {
|
|||
stream.seek(namedPointsOffs);
|
||||
_namedPoints.load(namedPointsCount, stream);
|
||||
|
||||
// Load palettes
|
||||
stream.seek(0x18);
|
||||
_palettesCount = stream.readUint16LE();
|
||||
_palettes = new Palette[_palettesCount];
|
||||
stream.seek(0x3C);
|
||||
uint32 palettesOffs = stream.readUint32LE();
|
||||
debug(0, "_palettesCount: %d", _palettesCount);
|
||||
for (uint i = 0; i < _palettesCount; ++i) {
|
||||
stream.seek(palettesOffs + i * 8);
|
||||
_palettes[i].load(data, stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int BackgroundResource::findMasterBgIndex() {
|
||||
|
@ -255,7 +282,7 @@ bool BackgroundResource::findNamedPoint(uint32 namedPointId, Common::Point &pt)
|
|||
|
||||
// BackgroundItem
|
||||
|
||||
BackgroundItem::BackgroundItem(IllusionsEngine *vm) : _vm(vm), _tag(0), _pauseCtr(0), _bgRes(0) {
|
||||
BackgroundItem::BackgroundItem(IllusionsEngine *vm) : _vm(vm), _tag(0), _pauseCtr(0), _bgRes(0), _savedPalette(0) {
|
||||
}
|
||||
|
||||
BackgroundItem::~BackgroundItem() {
|
||||
|
@ -282,6 +309,41 @@ void BackgroundItem::freeSurface() {
|
|||
}
|
||||
|
||||
void BackgroundItem::drawTiles(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
|
||||
switch (_vm->getGameId()) {
|
||||
case kGameIdDuckman:
|
||||
drawTiles8(surface, tileMap, tilePixels);
|
||||
break;
|
||||
case kGameIdBBDOU:
|
||||
drawTiles16(surface, tileMap, tilePixels);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundItem::drawTiles8(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
|
||||
const int kTileWidth = 32;
|
||||
const int kTileHeight = 8;
|
||||
const int kTileSize = kTileWidth * kTileHeight;
|
||||
uint tileMapIndex = 0;
|
||||
for (int tileY = 0; tileY < tileMap._height; ++tileY) {
|
||||
int tileDestY = tileY * kTileHeight;
|
||||
int tileDestH = MIN(kTileHeight, surface->h - tileDestY);
|
||||
for (int tileX = 0; tileX < tileMap._width; ++tileX) {
|
||||
int tileDestX = tileX * kTileWidth;
|
||||
int tileDestW = MIN(kTileWidth, surface->w - tileDestX);
|
||||
uint16 tileIndex = READ_LE_UINT16(tileMap._map + 2 * tileMapIndex);
|
||||
++tileMapIndex;
|
||||
byte *src = tilePixels + (tileIndex - 1) * kTileSize;
|
||||
byte *dst = (byte*)surface->getBasePtr(tileDestX, tileDestY);
|
||||
for (int h = 0; h < tileDestH; ++h) {
|
||||
memcpy(dst, src, tileDestW);
|
||||
dst += surface->pitch;
|
||||
src += kTileWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundItem::drawTiles16(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
|
||||
const int kTileWidth = 32;
|
||||
const int kTileHeight = 8;
|
||||
const int kTileSize = kTileWidth * kTileHeight * 2;
|
||||
|
@ -318,10 +380,8 @@ void BackgroundItem::pause() {
|
|||
*/
|
||||
// TODO _vm->setDefPointDimensions1();
|
||||
_vm->_camera->getActiveState(_savedCameraState);
|
||||
/* Unused
|
||||
_savedPalette = malloc(1024);
|
||||
savePalette(_savedPalette);
|
||||
*/
|
||||
_savedPalette = new byte[1024];
|
||||
_vm->_screen->getPalette(_savedPalette);
|
||||
freeSurface();
|
||||
}
|
||||
}
|
||||
|
@ -335,11 +395,9 @@ void BackgroundItem::unpause() {
|
|||
krndictAddID(_bgRes->_item48s[i].id, _bgRes->_item48s[i]);
|
||||
*/
|
||||
initSurface();
|
||||
/* Unused
|
||||
restorePalette(_savedPalette, 1, 256);
|
||||
free(_savedPalette);
|
||||
_vm->_screen->setPalette(_savedPalette, 1, 256);
|
||||
delete[] _savedPalette;
|
||||
_savedPalette = 0;
|
||||
*/
|
||||
// TODO _vm->_screen->_fadeClear();
|
||||
_vm->_camera->setActiveState(_savedCameraState);
|
||||
_vm->_backgroundItems->refreshPan();
|
||||
|
@ -437,8 +495,4 @@ bool BackgroundItems::findActiveBackgroundNamedPoint(uint32 namedPointId, Common
|
|||
return backgroundResource ? backgroundResource->findNamedPoint(namedPointId, pt) : false;
|
||||
}
|
||||
|
||||
BackgroundItem *BackgroundItems::debugFirst() {
|
||||
return *(_items.begin());
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
|
|
@ -101,6 +101,13 @@ points dd ?
|
|||
BgResource_PathWalkPoints ends
|
||||
#endif
|
||||
|
||||
struct Palette {
|
||||
uint16 _count;
|
||||
uint16 _unk;
|
||||
byte *_palette;
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
struct BackgroundObject {
|
||||
uint32 _objectId;
|
||||
uint16 _flags;
|
||||
|
@ -120,6 +127,8 @@ public:
|
|||
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
|
||||
public:
|
||||
|
||||
uint _paletteIndex;
|
||||
|
||||
uint _bgInfosCount;
|
||||
BgInfo *_bgInfos;
|
||||
|
||||
|
@ -134,6 +143,9 @@ public:
|
|||
|
||||
NamedPoints _namedPoints;
|
||||
|
||||
uint _palettesCount;
|
||||
Palette *_palettes;
|
||||
|
||||
};
|
||||
|
||||
const uint kMaxBackgroundItemSurfaces = 3;
|
||||
|
@ -156,7 +168,9 @@ public:
|
|||
Common::Point _panPoints[kMaxBackgroundItemSurfaces];
|
||||
Graphics::Surface *_surfaces[kMaxBackgroundItemSurfaces];
|
||||
CameraState _savedCameraState;
|
||||
// TODO? byte *savedPalette;
|
||||
byte *_savedPalette;
|
||||
void drawTiles8(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels);
|
||||
void drawTiles16(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels);
|
||||
};
|
||||
|
||||
class BackgroundItems {
|
||||
|
@ -173,7 +187,6 @@ public:
|
|||
WidthHeight getMasterBgDimensions();
|
||||
void refreshPan();
|
||||
bool findActiveBackgroundNamedPoint(uint32 namedPointId, Common::Point &pt);
|
||||
BackgroundItem *debugFirst();
|
||||
//protected:
|
||||
public:
|
||||
typedef Common::List<BackgroundItem*> Items;
|
||||
|
|
|
@ -79,15 +79,4 @@ void Cursor::hide() {
|
|||
}
|
||||
}
|
||||
|
||||
void Cursor::cursorControlRoutine(Control *control, uint32 deltaTime) {
|
||||
_control->_actor->_seqCodeValue1 = 100 * deltaTime;
|
||||
if (_control->_actor->_flags & 1) {
|
||||
if (_status == 2) {
|
||||
// Unused nullsub_1(control);
|
||||
} else if (_status == 3) {
|
||||
// TODO _vm->_shellMgr->handleMouse(_control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
|
|
@ -37,7 +37,8 @@ public:
|
|||
void show();
|
||||
void hide();
|
||||
void cursorControlRoutine(Control *control, uint32 deltaTime);
|
||||
protected:
|
||||
//protected:
|
||||
public:
|
||||
IllusionsEngine *_vm;
|
||||
Control *_control;
|
||||
uint32 _sequenceId;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/illusions_bbdou.h"
|
||||
#include "illusions/illusions_duckman.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
|
@ -33,16 +34,12 @@
|
|||
static const PlainGameDescriptor illusionsGames[] = {
|
||||
{ "illusions", "Illusions engine game" },
|
||||
{ "bbdou", "Beavis and Butthead Do U" },
|
||||
{ "duckman", "Duckman" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
struct IllusionsGameDescription {
|
||||
ADGameDescription desc;
|
||||
int gameId;
|
||||
};
|
||||
|
||||
static const IllusionsGameDescription gameDescriptions[] = {
|
||||
{
|
||||
{
|
||||
|
@ -57,6 +54,19 @@ static const IllusionsGameDescription gameDescriptions[] = {
|
|||
kGameIdBBDOU
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"duckman",
|
||||
0,
|
||||
AD_ENTRY1s("duckman.gam", "172c0514f3793041718159cf9cf9935f", 29560832),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
kGameIdDuckman
|
||||
},
|
||||
|
||||
{AD_TABLE_END_MARKER, 0}
|
||||
};
|
||||
|
||||
|
@ -172,7 +182,10 @@ bool IllusionsMetaEngine::createInstance(OSystem *syst, Engine **engine, const A
|
|||
if (gd) {
|
||||
switch (gd->gameId) {
|
||||
case Illusions::kGameIdBBDOU:
|
||||
*engine = new Illusions::IllusionsEngine_BBDOU(syst, desc);
|
||||
*engine = new Illusions::IllusionsEngine_BBDOU(syst, gd);
|
||||
break;
|
||||
case Illusions::kGameIdDuckman:
|
||||
*engine = new Illusions::IllusionsEngine_Duckman(syst, gd);
|
||||
break;
|
||||
default:
|
||||
error("Unknown game id");
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
namespace Illusions {
|
||||
|
||||
IllusionsEngine::IllusionsEngine(OSystem *syst, const ADGameDescription *gd) :
|
||||
IllusionsEngine::IllusionsEngine(OSystem *syst, const IllusionsGameDescription *gd) :
|
||||
Engine(syst), _gameDescription(gd) {
|
||||
|
||||
_random = new Common::RandomSource("illusions");
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "common/system.h"
|
||||
#include "common/winexe.h"
|
||||
#include "common/winexe_pe.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
#include "engines/engine.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
|
@ -74,15 +75,21 @@ enum {
|
|||
kGameIdDuckman = 2
|
||||
};
|
||||
|
||||
struct IllusionsGameDescription {
|
||||
ADGameDescription desc;
|
||||
int gameId;
|
||||
};
|
||||
|
||||
class IllusionsEngine : public Engine {
|
||||
public:
|
||||
IllusionsEngine(OSystem *syst, const ADGameDescription *gd);
|
||||
IllusionsEngine(OSystem *syst, const IllusionsGameDescription *gd);
|
||||
~IllusionsEngine();
|
||||
const Common::String getTargetName() { return _targetName; }
|
||||
private:
|
||||
const ADGameDescription *_gameDescription;
|
||||
const IllusionsGameDescription *_gameDescription;
|
||||
Graphics::PixelFormat _pixelFormat;
|
||||
public:
|
||||
|
||||
Common::RandomSource *_random;
|
||||
Dictionary *_dict;
|
||||
ResourceSystem *_resSys;
|
||||
|
@ -99,7 +106,6 @@ public:
|
|||
ScriptOpcodes *_scriptOpcodes;
|
||||
SpecialCode *_specialCode;
|
||||
ThreadList *_threads;
|
||||
Cursor *_cursor;
|
||||
|
||||
ScriptResource *_scriptResource;
|
||||
|
||||
|
@ -114,6 +120,10 @@ public:
|
|||
|
||||
int16 _menuChoiceOfs;
|
||||
|
||||
int getGameId() const {
|
||||
return _gameDescription->gameId;
|
||||
}
|
||||
|
||||
Common::Point *getObjectActorPositionPtr(uint32 objectId);
|
||||
uint32 getElapsedUpdateTime();
|
||||
int updateActors();
|
||||
|
@ -143,6 +153,13 @@ public:
|
|||
virtual uint32 getPrevScene() = 0;
|
||||
virtual uint32 getCurrentScene() = 0;
|
||||
|
||||
virtual bool isCursorObject(uint32 actorTypeId, uint32 objectId) = 0;
|
||||
virtual void setCursorControlRoutine(Control *control) = 0;
|
||||
virtual void placeCursorControl(Control *control, uint32 sequenceId) = 0;
|
||||
virtual void setCursorControl(Control *control) = 0;
|
||||
virtual void showCursor() = 0;
|
||||
virtual void hideCursor() = 0;
|
||||
|
||||
virtual void startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) = 0;
|
||||
virtual uint32 startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10) = 0;
|
||||
|
|
|
@ -172,7 +172,7 @@ bool ActiveScenes::isSceneActive(uint32 sceneId) {
|
|||
|
||||
// IllusionsEngine_BBDOU
|
||||
|
||||
IllusionsEngine_BBDOU::IllusionsEngine_BBDOU(OSystem *syst, const ADGameDescription *gd)
|
||||
IllusionsEngine_BBDOU::IllusionsEngine_BBDOU(OSystem *syst, const IllusionsGameDescription *gd)
|
||||
: IllusionsEngine(syst, gd) {
|
||||
}
|
||||
|
||||
|
@ -188,12 +188,9 @@ Common::Error IllusionsEngine_BBDOU::run() {
|
|||
SearchMan.addSubDirectoryMatching(gameDataDir, "video");
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "voice");
|
||||
|
||||
Graphics::PixelFormat pixelFormat16(2, 5, 6, 5, 0, 11, 5, 0, 0);
|
||||
initGraphics(640, 480, true, &pixelFormat16);
|
||||
|
||||
_dict = new Dictionary();
|
||||
|
||||
_resSys = new ResourceSystem();
|
||||
_resSys = new ResourceSystem(this);
|
||||
_resSys->addResourceLoader(0x00060000, new ActorResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00080000, new SoundGroupResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x000D0000, new ScriptResourceLoader(this));
|
||||
|
@ -203,7 +200,7 @@ Common::Error IllusionsEngine_BBDOU::run() {
|
|||
_resSys->addResourceLoader(0x00120000, new FontResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00170000, new SpecialCodeLoader(this));
|
||||
|
||||
_screen = new Screen(this);
|
||||
_screen = new Screen(this, 640, 480, 16);
|
||||
_input = new Input();
|
||||
_scriptMan = new ScriptMan(this);
|
||||
_actorItems = new ActorItems(this);
|
||||
|
@ -281,12 +278,9 @@ bool IllusionsEngine_BBDOU::hasFeature(EngineFeature f) const {
|
|||
|
||||
bool IllusionsEngine_BBDOU::causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) {
|
||||
uint32 codeOffs;
|
||||
bool r =
|
||||
return
|
||||
_triggerFunctions->find(sceneId, verbId, objectId2, objectId) ||
|
||||
findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs);
|
||||
debug(3, "causeIsDeclared() sceneId: %08X; verbId: %08X; objectId2: %08X; objectId: %08X -> %d",
|
||||
sceneId, verbId, objectId2, objectId, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) {
|
||||
|
@ -352,6 +346,45 @@ uint32 IllusionsEngine_BBDOU::getPrevScene() {
|
|||
return _prevSceneId;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_BBDOU::isCursorObject(uint32 actorTypeId, uint32 objectId) {
|
||||
return actorTypeId == 0x50001 && objectId == 0x40004;
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::setCursorControlRoutine(Control *control) {
|
||||
control->_actor->setControlRoutine(new Common::Functor2Mem<Control*, uint32, void, IllusionsEngine_BBDOU>
|
||||
(this, &IllusionsEngine_BBDOU::cursorControlRoutine));
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::placeCursorControl(Control *control, uint32 sequenceId) {
|
||||
_cursor->place(control, sequenceId);
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::setCursorControl(Control *control) {
|
||||
_cursor->setControl(control);
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::showCursor() {
|
||||
_cursor->show();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::hideCursor() {
|
||||
_cursor->hide();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::cursorControlRoutine(Control *control, uint32 deltaTime) {
|
||||
control->_actor->_seqCodeValue1 = 100 * deltaTime;
|
||||
if (control->_actor->_flags & 1) {
|
||||
switch (_cursor->_status) {
|
||||
case 2:
|
||||
// Unused nullsub_1(control);
|
||||
break;
|
||||
case 3:
|
||||
// TODO _vm->_shellMgr->handleMouse(control);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) {
|
||||
startScriptThread(threadId, callingThreadId, 0, 0, 0);
|
||||
}
|
||||
|
|
|
@ -83,13 +83,14 @@ protected:
|
|||
|
||||
class IllusionsEngine_BBDOU : public IllusionsEngine {
|
||||
public:
|
||||
IllusionsEngine_BBDOU(OSystem *syst, const ADGameDescription *gd);
|
||||
IllusionsEngine_BBDOU(OSystem *syst, const IllusionsGameDescription *gd);
|
||||
protected:
|
||||
virtual Common::Error run();
|
||||
virtual bool hasFeature(EngineFeature f) const;
|
||||
public:
|
||||
ScriptMan *_scriptMan;
|
||||
TriggerFunctions *_triggerFunctions;
|
||||
Cursor *_cursor;
|
||||
|
||||
ActiveScenes _activeScenes;
|
||||
uint32 _prevSceneId;
|
||||
|
@ -113,8 +114,16 @@ public:
|
|||
Control *getObjectControl(uint32 objectId);
|
||||
Common::Point getNamedPointPosition(uint32 namedPointId);
|
||||
uint32 getPriorityFromBase(int16 priority);
|
||||
uint32 getPrevScene();
|
||||
uint32 getCurrentScene();
|
||||
uint32 getPrevScene();
|
||||
|
||||
bool isCursorObject(uint32 actorTypeId, uint32 objectId);
|
||||
void setCursorControlRoutine(Control *control);
|
||||
void placeCursorControl(Control *control, uint32 sequenceId);
|
||||
void setCursorControl(Control *control);
|
||||
void showCursor();
|
||||
void hideCursor();
|
||||
void cursorControlRoutine(Control *control, uint32 deltaTime);
|
||||
|
||||
void startScriptThreadSimple(uint32 threadId, uint32 callingThreadId);
|
||||
void startScriptThread(uint32 threadId, uint32 callingThreadId,
|
||||
|
|
440
engines/illusions/illusions_duckman.cpp
Normal file
440
engines/illusions/illusions_duckman.cpp
Normal file
|
@ -0,0 +1,440 @@
|
|||
/* 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 "illusions/illusions_duckman.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/actorresource.h"
|
||||
#include "illusions/backgroundresource.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/cursor.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/fontresource.h"
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/midiresource.h"
|
||||
#include "illusions/resourcesystem.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "illusions/scriptopcodes_duckman.h"
|
||||
#include "illusions/scriptresource.h"
|
||||
#include "illusions/scriptman.h"
|
||||
#include "illusions/soundresource.h"
|
||||
#include "illusions/specialcode.h"
|
||||
//TODO#include "illusions/bbdou/bbdou_specialcode.h"
|
||||
#include "illusions/talkresource.h"
|
||||
#include "illusions/thread.h"
|
||||
#include "illusions/time.h"
|
||||
#include "illusions/updatefunctions.h"
|
||||
|
||||
#include "illusions/abortablethread.h"
|
||||
#include "illusions/scriptthread.h"
|
||||
#include "illusions/talkthread_duckman.h"
|
||||
#include "illusions/timerthread.h"
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/error.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/timer.h"
|
||||
#include "engines/util.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/fontman.h"
|
||||
#include "graphics/palette.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// IllusionsEngine_Duckman
|
||||
|
||||
IllusionsEngine_Duckman::IllusionsEngine_Duckman(OSystem *syst, const IllusionsGameDescription *gd)
|
||||
: IllusionsEngine(syst, gd) {
|
||||
}
|
||||
|
||||
Common::Error IllusionsEngine_Duckman::run() {
|
||||
|
||||
// Init search paths
|
||||
const Common::FSNode gameDataDir(ConfMan.get("path"));
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "music");
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "sfx");
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "video");
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "voice");
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "x");// DEBUG until gam reader is done
|
||||
|
||||
_dict = new Dictionary();
|
||||
|
||||
_resSys = new ResourceSystem(this);
|
||||
_resSys->addResourceLoader(0x00060000, new ActorResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00080000, new SoundGroupResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x000A0000, new MidiGroupResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x000D0000, new ScriptResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x000F0000, new TalkResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00100000, new ActorResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00110000, new BackgroundResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00120000, new FontResourceLoader(this));
|
||||
|
||||
_screen = new Screen(this, 320, 200, 8);
|
||||
_input = new Input();
|
||||
_actorItems = new ActorItems(this);
|
||||
_backgroundItems = new BackgroundItems(this);
|
||||
_camera = new Camera(this);
|
||||
_controls = new Controls(this);
|
||||
_talkItems = new TalkItems(this);
|
||||
_threads = new ThreadList(this);
|
||||
|
||||
_scriptOpcodes = new ScriptOpcodes_Duckman(this);
|
||||
_stack = new ScriptStack();
|
||||
|
||||
// TODO Move to own class
|
||||
_resGetCtr = 0;
|
||||
_unpauseControlActorFlag = false;
|
||||
_lastUpdateTime = 0;
|
||||
|
||||
_pauseCtr = 0;
|
||||
_doScriptThreadInit = false;
|
||||
_field8 = 1;
|
||||
_fieldA = 0;
|
||||
_fieldE = 240;
|
||||
|
||||
_globalSceneId = 0x00010003;
|
||||
|
||||
_resSys->loadResource(0x000D0001, 0x00010001, 0);
|
||||
|
||||
initActiveScenes();
|
||||
startScriptThread(0x00020004, 0);
|
||||
_doScriptThreadInit = true;
|
||||
|
||||
while (!shouldQuit()) {
|
||||
_threads->updateThreads();
|
||||
updateActors();
|
||||
updateSequences();
|
||||
updateGraphics();
|
||||
_screen->updateSprites();
|
||||
_screen->updatePalette();
|
||||
_system->updateScreen();
|
||||
updateEvents();
|
||||
_system->delayMillis(10);
|
||||
}
|
||||
|
||||
delete _stack;
|
||||
delete _scriptOpcodes;
|
||||
|
||||
delete _threads;
|
||||
delete _talkItems;
|
||||
delete _controls;
|
||||
delete _camera;
|
||||
delete _backgroundItems;
|
||||
delete _actorItems;
|
||||
delete _input;
|
||||
delete _screen;
|
||||
delete _resSys;
|
||||
delete _dict;
|
||||
|
||||
debug("Ok");
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_Duckman::hasFeature(EngineFeature f) const {
|
||||
return
|
||||
false;
|
||||
/*
|
||||
(f == kSupportsRTL) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
*/
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::loadSpecialCode(uint32 resId) {
|
||||
//TODO _specialCode = new BbdouSpecialCode(this);
|
||||
//TODO _specialCode->init();
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::unloadSpecialCode(uint32 resId) {
|
||||
//TODO delete _specialCode;
|
||||
//TODO _specialCode = 0;
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::notifyThreadId(uint32 &threadId) {
|
||||
if (threadId) {
|
||||
uint32 tempThreadId = threadId;
|
||||
threadId = 0;
|
||||
_threads->notifyId(tempThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
Control *IllusionsEngine_Duckman::getObjectControl(uint32 objectId) {
|
||||
return _dict->getObjectControl(objectId);
|
||||
}
|
||||
|
||||
Common::Point IllusionsEngine_Duckman::getNamedPointPosition(uint32 namedPointId) {
|
||||
Common::Point pt;
|
||||
Common::Point currPan = _camera->getCurrentPan();
|
||||
if (_backgroundItems->findActiveBackgroundNamedPoint(namedPointId, pt)) {
|
||||
return pt;
|
||||
} else if (namedPointId - 0x00070001 > 209) {
|
||||
if (_controls->findNamedPoint(namedPointId, pt)) {
|
||||
return pt;
|
||||
} else {
|
||||
return currPan;
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
//debug("getNamedPointPosition(%08X) UNKNOWN", namedPointId);
|
||||
return Common::Point(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::getPriorityFromBase(int16 priority) {
|
||||
return 32000000 * priority;
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::getCurrentScene() {
|
||||
return _activeScenes[_activeScenesCount];
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::getPrevScene() {
|
||||
uint index = _activeScenesCount - 1;
|
||||
if (_activeScenesCount == 1)
|
||||
index = 5;
|
||||
return _activeScenes[index];
|
||||
}
|
||||
|
||||
bool IllusionsEngine_Duckman::isCursorObject(uint32 actorTypeId, uint32 objectId) {
|
||||
return actorTypeId == 0x50001;
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::setCursorControlRoutine(Control *control) {
|
||||
control->_actor->setControlRoutine(new Common::Functor2Mem<Control*, uint32, void, IllusionsEngine_Duckman>
|
||||
(this, &IllusionsEngine_Duckman::cursorControlRoutine));
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::placeCursorControl(Control *control, uint32 sequenceId) {
|
||||
// TODO
|
||||
control->_actor->_actorIndex = 2;
|
||||
// TODO _cursor->place(control, sequenceId);
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::setCursorControl(Control *control) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::showCursor() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::hideCursor() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::cursorControlRoutine(Control *control, uint32 deltaTime) {
|
||||
control->_actor->_seqCodeValue1 = 100 * deltaTime;
|
||||
// TODO
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) {
|
||||
startScriptThread(threadId, callingThreadId);
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::startScriptThread(uint32 threadId, uint32 callingThreadId) {
|
||||
debug(2, "Starting script thread %08X", threadId);
|
||||
byte *scriptCodeIp = _scriptResource->getThreadCode(threadId);
|
||||
newScriptThread(threadId, callingThreadId, 0, scriptCodeIp);
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::startAbortableTimerThread(uint32 duration, uint32 threadId) {
|
||||
return newTimerThread(duration, threadId, true);
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::startTimerThread(uint32 duration, uint32 threadId) {
|
||||
return newTimerThread(duration, threadId, false);
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::startAbortableThread(byte *scriptCodeIp1, byte *scriptCodeIp2, uint32 callingThreadId) {
|
||||
uint32 tempThreadId = newTempThreadId();
|
||||
debug(2, "Starting abortable thread %08X", tempThreadId);
|
||||
uint32 scriptThreadId = startTempScriptThread(scriptCodeIp1, tempThreadId, 0, 0, 0);
|
||||
AbortableThread *abortableThread = new AbortableThread(this, tempThreadId, callingThreadId, 0,
|
||||
scriptThreadId, scriptCodeIp2);
|
||||
_threads->startThread(abortableThread);
|
||||
return tempThreadId;
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::startTalkThread(uint32 objectId, uint32 talkId, uint32 sequenceId1,
|
||||
uint32 sequenceId2, uint32 callingThreadId) {
|
||||
debug(2, "Starting talk thread");
|
||||
uint32 tempThreadId = newTempThreadId();
|
||||
TalkThread_Duckman *talkThread = new TalkThread_Duckman(this, tempThreadId, callingThreadId, 0,
|
||||
objectId, talkId, sequenceId1, sequenceId2);
|
||||
_threads->startThread(talkThread);
|
||||
return tempThreadId;
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10) {
|
||||
uint32 tempThreadId = newTempThreadId();
|
||||
debug(2, "Starting temp script thread %08X", tempThreadId);
|
||||
newScriptThread(tempThreadId, callingThreadId, 0, scriptCodeIp);
|
||||
return tempThreadId;
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::newScriptThread(uint32 threadId, uint32 callingThreadId, uint notifyFlags,
|
||||
byte *scriptCodeIp) {
|
||||
ScriptThread *scriptThread = new ScriptThread(this, threadId, callingThreadId, notifyFlags,
|
||||
scriptCodeIp, 0, 0, 0);
|
||||
_threads->startThread(scriptThread);
|
||||
if (_pauseCtr > 0)
|
||||
scriptThread->pause();
|
||||
if (_doScriptThreadInit) {
|
||||
int updateResult = kTSRun;
|
||||
while (scriptThread->_pauseCtr <= 0 && updateResult != kTSTerminate && updateResult != kTSYield)
|
||||
updateResult = scriptThread->update();
|
||||
}
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::newTimerThread(uint32 duration, uint32 callingThreadId, bool isAbortable) {
|
||||
uint32 tempThreadId = newTempThreadId();
|
||||
TimerThread *timerThread = new TimerThread(this, tempThreadId, callingThreadId, 0,
|
||||
duration, isAbortable);
|
||||
_threads->startThread(timerThread);
|
||||
return tempThreadId;
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::newTempThreadId() {
|
||||
uint32 threadId = _nextTempThreadId + 2 * _scriptResource->_codeCount;
|
||||
if (threadId > 65535) {
|
||||
_nextTempThreadId = 0;
|
||||
threadId = 2 * _scriptResource->_codeCount;
|
||||
}
|
||||
++_nextTempThreadId;
|
||||
return 0x00020000 | threadId;
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::initActiveScenes() {
|
||||
_activeScenesCount = 0;
|
||||
_activeScenes[0] = 0xEFEF;
|
||||
pushActiveScene(0x10000);
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::pushActiveScene(uint32 sceneId) {
|
||||
++_activeScenesCount;
|
||||
if (_activeScenesCount >= 6)
|
||||
_activeScenesCount = 1;
|
||||
_activeScenes[_activeScenesCount] = sceneId;
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::popActiveScene() {
|
||||
--_activeScenesCount;
|
||||
if (_activeScenesCount == 0)
|
||||
_activeScenesCount = 5;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_Duckman::loadScene(uint32 sceneId) {
|
||||
ProgInfo *progInfo = _scriptResource->getProgInfo(sceneId & 0xFFFF);
|
||||
if (!progInfo)
|
||||
return false;
|
||||
pushActiveScene(sceneId);
|
||||
uint resourcesCount;
|
||||
uint32 *resources;
|
||||
progInfo->getResources(resourcesCount, resources);
|
||||
for (uint i = 0; i < resourcesCount; ++i)
|
||||
_resSys->loadResource(resources[i], sceneId, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_Duckman::enterScene(uint32 sceneId, uint32 threadId) {
|
||||
if (loadScene(sceneId)) {
|
||||
if (threadId)
|
||||
startScriptThread(threadId, 0);
|
||||
return true;
|
||||
}
|
||||
// TODO startScriptThread2(0x10002, 0x20001, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::exitScene() {
|
||||
popActiveScene();
|
||||
}
|
||||
|
||||
bool IllusionsEngine_Duckman::changeScene(uint32 sceneId, uint32 threadId, uint32 callerThreadId) {
|
||||
uint32 currSceneId = getCurrentScene();
|
||||
if (currSceneId != 0x10003)
|
||||
dumpCurrSceneFiles(currSceneId, callerThreadId);
|
||||
_threads->terminateThreads(callerThreadId);
|
||||
_controls->destroyControls();
|
||||
_resSys->unloadSceneResources(0x10003, 0x10001);
|
||||
if (enterScene(sceneId, threadId)) {
|
||||
// TODO GameStates_writeStates(sceneId, threadId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::enterPause(uint32 sceneId, uint32 threadId) {
|
||||
_threads->suspendThreads(threadId);
|
||||
_controls->pauseControls();
|
||||
_actorItems->pauseByTag(sceneId);
|
||||
_backgroundItems->pauseByTag(sceneId);
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::leavePause(uint32 sceneId, uint32 threadId) {
|
||||
_backgroundItems->unpauseByTag(sceneId);
|
||||
_actorItems->unpauseByTag(sceneId);
|
||||
_controls->unpauseControls();
|
||||
_threads->notifyThreads(threadId);
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::dumpActiveScenes(uint32 sceneId, uint32 threadId) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::dumpCurrSceneFiles(uint32 sceneId, uint32 threadId) {
|
||||
// TODO UpdateFunctions_disableByTag(sceneId);
|
||||
_threads->terminateActiveThreads(threadId);
|
||||
_threads->terminateThreadsByTag(sceneId, threadId);
|
||||
_controls->destroyActiveControls();
|
||||
_resSys->unloadResourcesByTag(sceneId);
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::setSceneIdThreadId(uint32 theSceneId, uint32 theThreadId) {
|
||||
_theSceneId = theSceneId;
|
||||
_theThreadId = theThreadId;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_Duckman::findTriggerCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs) {
|
||||
ProgInfo *progInfo = _scriptResource->getProgInfo(sceneId & 0xFFFF);
|
||||
if (progInfo)
|
||||
return progInfo->findTriggerCause(verbId, objectId2, objectId, codeOffs);
|
||||
return false;
|
||||
}
|
||||
|
||||
void IllusionsEngine_Duckman::reset() {
|
||||
_scriptResource->_blockCounters.clear();
|
||||
_scriptResource->_properties.clear();
|
||||
// TODO script_sub_417FF0(1, 0);
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_Duckman::getObjectActorTypeId(uint32 objectId) {
|
||||
return _scriptResource->getObjectActorTypeId(objectId);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
111
engines/illusions/illusions_duckman.h
Normal file
111
engines/illusions/illusions_duckman.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_ILLUSIONS_DUCKMAN_H
|
||||
#define ILLUSIONS_ILLUSIONS_DUCKMAN_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class Dictionary;
|
||||
class ScriptStack;
|
||||
|
||||
class IllusionsEngine_Duckman : public IllusionsEngine {
|
||||
public:
|
||||
IllusionsEngine_Duckman(OSystem *syst, const IllusionsGameDescription *gd);
|
||||
protected:
|
||||
virtual Common::Error run();
|
||||
virtual bool hasFeature(EngineFeature f) const;
|
||||
public:
|
||||
|
||||
// TODO ActiveScenes _activeScenes;
|
||||
uint32 _prevSceneId;
|
||||
uint32 _theSceneId;
|
||||
uint32 _theThreadId;
|
||||
uint32 _globalSceneId;
|
||||
|
||||
int _pauseCtr;
|
||||
ScriptStack *_stack;
|
||||
bool _doScriptThreadInit;
|
||||
|
||||
uint32 _nextTempThreadId;
|
||||
|
||||
uint _activeScenesCount;
|
||||
uint32 _activeScenes[6];
|
||||
|
||||
void loadSpecialCode(uint32 resId);
|
||||
void unloadSpecialCode(uint32 resId);
|
||||
void notifyThreadId(uint32 &threadId);
|
||||
Control *getObjectControl(uint32 objectId);
|
||||
Common::Point getNamedPointPosition(uint32 namedPointId);
|
||||
uint32 getPriorityFromBase(int16 priority);
|
||||
uint32 getCurrentScene();
|
||||
uint32 getPrevScene();
|
||||
|
||||
bool isCursorObject(uint32 actorTypeId, uint32 objectId);
|
||||
void setCursorControlRoutine(Control *control);
|
||||
void placeCursorControl(Control *control, uint32 sequenceId);
|
||||
void setCursorControl(Control *control);
|
||||
void showCursor();
|
||||
void hideCursor();
|
||||
void cursorControlRoutine(Control *control, uint32 deltaTime);
|
||||
|
||||
void startScriptThreadSimple(uint32 threadId, uint32 callingThreadId);
|
||||
void startScriptThread(uint32 threadId, uint32 callingThreadId);
|
||||
uint32 startAbortableTimerThread(uint32 duration, uint32 threadId);
|
||||
uint32 startTimerThread(uint32 duration, uint32 threadId);
|
||||
uint32 startAbortableThread(byte *scriptCodeIp1, byte *scriptCodeIp2, uint32 callingThreadId);
|
||||
uint32 startTalkThread(uint32 objectId, uint32 talkId, uint32 sequenceId1,
|
||||
uint32 sequenceId2, uint32 callingThreadId);
|
||||
uint32 startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10);
|
||||
void newScriptThread(uint32 threadId, uint32 callingThreadId, uint notifyFlags,
|
||||
byte *scriptCodeIp);
|
||||
uint32 newTimerThread(uint32 duration, uint32 callingThreadId, bool isAbortable);
|
||||
uint32 newTempThreadId();
|
||||
|
||||
void initActiveScenes();
|
||||
void pushActiveScene(uint32 sceneId);
|
||||
void popActiveScene();
|
||||
bool loadScene(uint32 sceneId);
|
||||
bool enterScene(uint32 sceneId, uint32 threadId);
|
||||
void exitScene();
|
||||
bool changeScene(uint32 sceneId, uint32 threadId, uint32 callerThreadId);
|
||||
void enterPause(uint32 sceneId, uint32 threadId);
|
||||
void leavePause(uint32 sceneId, uint32 threadId);
|
||||
void dumpActiveScenes(uint32 sceneId, uint32 threadId);
|
||||
void dumpCurrSceneFiles(uint32 sceneId, uint32 threadId);
|
||||
|
||||
void setSceneIdThreadId(uint32 theSceneId, uint32 theThreadId);
|
||||
bool findTriggerCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs);
|
||||
void reset();
|
||||
|
||||
uint32 getObjectActorTypeId(uint32 objectId);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_ILLUSIONS_H
|
48
engines/illusions/midiresource.cpp
Normal file
48
engines/illusions/midiresource.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* 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 "illusions/illusions.h"
|
||||
#include "illusions/midiresource.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// MidiGroupResourceLoader
|
||||
|
||||
void MidiGroupResourceLoader::load(Resource *resource) {
|
||||
debug("MidiGroupResourceLoader::load() Loading midi group %08X...", resource->_resId);
|
||||
|
||||
// TODO
|
||||
|
||||
}
|
||||
|
||||
void MidiGroupResourceLoader::unload(Resource *resource) {
|
||||
}
|
||||
|
||||
void MidiGroupResourceLoader::buildFilename(Resource *resource) {
|
||||
resource->_filename = Common::String::format("%08X.fnt", resource->_resId);
|
||||
}
|
||||
|
||||
bool MidiGroupResourceLoader::isFlag(int flag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
47
engines/illusions/midiresource.h
Normal file
47
engines/illusions/midiresource.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_MIDIRESOURCE_H
|
||||
#define ILLUSIONS_MIDIRESOURCE_H
|
||||
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/resourcesystem.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine;
|
||||
|
||||
class MidiGroupResourceLoader : public BaseResourceLoader {
|
||||
public:
|
||||
MidiGroupResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
|
||||
virtual ~MidiGroupResourceLoader() {}
|
||||
virtual void load(Resource *resource);
|
||||
virtual void unload(Resource *resource);
|
||||
virtual void buildFilename(Resource *resource);
|
||||
virtual bool isFlag(int flag);
|
||||
protected:
|
||||
IllusionsEngine *_vm;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_SOUNDRESOURCE_H
|
|
@ -18,12 +18,15 @@ MODULE_OBJS := \
|
|||
graphics.o \
|
||||
illusions.o \
|
||||
illusions_bbdou.o \
|
||||
illusions_duckman.o \
|
||||
input.o \
|
||||
midiresource.o \
|
||||
resourcesystem.o \
|
||||
screen.o \
|
||||
scriptman.o \
|
||||
scriptopcodes.o \
|
||||
scriptopcodes_bbdou.o \
|
||||
scriptopcodes_duckman.o \
|
||||
scriptresource.o \
|
||||
scriptthread.o \
|
||||
sequenceopcodes.o \
|
||||
|
@ -31,6 +34,7 @@ MODULE_OBJS := \
|
|||
specialcode.o \
|
||||
talkresource.o \
|
||||
talkthread.o \
|
||||
talkthread_duckman.o \
|
||||
thread.o \
|
||||
time.o \
|
||||
timerthread.o \
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#include "illusions/resourcesystem.h"
|
||||
#include "illusions/illusions.h"
|
||||
|
||||
#include "common/algorithm.h"
|
||||
#include "common/debug.h"
|
||||
|
@ -38,6 +39,7 @@ void Resource::loadData() {
|
|||
_dataSize = fd.size();
|
||||
_data = (byte*)malloc(_dataSize);
|
||||
fd.read(_data, _dataSize);
|
||||
debug("Resource::loadData() OK");
|
||||
}
|
||||
|
||||
void Resource::unloadData() {
|
||||
|
@ -50,7 +52,8 @@ void Resource::unloadData() {
|
|||
|
||||
// ResourceSystem
|
||||
|
||||
ResourceSystem::ResourceSystem() {
|
||||
ResourceSystem::ResourceSystem(IllusionsEngine *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
ResourceSystem::~ResourceSystem() {
|
||||
|
@ -64,6 +67,7 @@ void ResourceSystem::addResourceLoader(uint32 resTypeId, BaseResourceLoader *res
|
|||
}
|
||||
|
||||
void ResourceSystem::loadResource(uint32 resId, uint32 tag, uint32 threadId) {
|
||||
debug("ResourceSystem::loadResource(%08X, %08X, %08X)", resId, tag, threadId);
|
||||
BaseResourceLoader *resourceLoader = getResourceLoader(resId);
|
||||
|
||||
Resource *resource = new Resource();
|
||||
|
@ -72,6 +76,7 @@ void ResourceSystem::loadResource(uint32 resId, uint32 tag, uint32 threadId) {
|
|||
resource->_tag = tag;
|
||||
resource->_threadId = threadId;
|
||||
resource->_resourceLoader = resourceLoader;
|
||||
resource->_gameId = _vm->getGameId();
|
||||
|
||||
resourceLoader->buildFilename(resource);
|
||||
|
||||
|
@ -108,6 +113,14 @@ void ResourceSystem::unloadResourcesByTag(uint32 tag) {
|
|||
}
|
||||
}
|
||||
|
||||
void ResourceSystem::unloadSceneResources(uint32 sceneId1, uint32 sceneId2) {
|
||||
ResourcesArrayIterator it = Common::find_if(_resources.begin(), _resources.end(), ResourceNotEqualByScenes(sceneId1, sceneId2));
|
||||
while (it != _resources.end()) {
|
||||
unloadResource(*it);
|
||||
it = Common::find_if(it, _resources.end(), ResourceNotEqualByScenes(sceneId1, sceneId2));
|
||||
}
|
||||
}
|
||||
|
||||
BaseResourceLoader *ResourceSystem::getResourceLoader(uint32 resId) {
|
||||
ResourceLoadersMapIterator it = _resourceLoaders.find(ResourceTypeId(resId));
|
||||
if (it != _resourceLoaders.end())
|
||||
|
@ -121,6 +134,7 @@ Resource *ResourceSystem::getResource(uint32 resId) {
|
|||
}
|
||||
|
||||
void ResourceSystem::unloadResource(Resource *resource) {
|
||||
debug("Unloading %08X... (tag: %08X)", resource->_resId, resource->_tag);
|
||||
resource->_resourceLoader->unload(resource);
|
||||
ResourcesArrayIterator it = Common::find_if(_resources.begin(), _resources.end(), ResourceEqualByValue(resource));
|
||||
if (it != _resources.end())
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace Illusions {
|
|||
#define ResourceTypeId(x) ((x) & 0xFFFF0000)
|
||||
|
||||
class BaseResourceLoader;
|
||||
class IllusionsEngine;
|
||||
|
||||
struct Resource {
|
||||
bool _loaded;
|
||||
|
@ -46,7 +47,8 @@ struct Resource {
|
|||
uint32 _dataSize;
|
||||
BaseResourceLoader *_resourceLoader;
|
||||
void *_refId;
|
||||
Common::String _filename; // TODO Check if this is needed
|
||||
int _gameId;
|
||||
Common::String _filename;
|
||||
Resource() : _loaded(false), _resId(0), _tag(0), _threadId(0), _data(0), _dataSize(0),
|
||||
_resourceLoader(0), _refId(0) {}
|
||||
~Resource() {
|
||||
|
@ -80,7 +82,7 @@ public:
|
|||
|
||||
class ResourceSystem {
|
||||
public:
|
||||
ResourceSystem();
|
||||
ResourceSystem(IllusionsEngine *vm);
|
||||
~ResourceSystem();
|
||||
|
||||
void addResourceLoader(uint32 resTypeId, BaseResourceLoader *resourceLoader);
|
||||
|
@ -89,10 +91,12 @@ public:
|
|||
void loadResource(uint32 resId, uint32 tag, uint32 threadId);
|
||||
void unloadResourceById(uint32 resId);
|
||||
void unloadResourcesByTag(uint32 tag);
|
||||
void unloadSceneResources(uint32 sceneId1, uint32 sceneId2);
|
||||
|
||||
protected:
|
||||
typedef Common::HashMap<uint32, BaseResourceLoader*> ResourceLoadersMap;
|
||||
typedef ResourceLoadersMap::iterator ResourceLoadersMapIterator;
|
||||
IllusionsEngine *_vm;
|
||||
ResourceLoadersMap _resourceLoaders;
|
||||
BaseResourceLoader *getResourceLoader(uint32 resId);
|
||||
|
||||
|
@ -124,6 +128,14 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
struct ResourceNotEqualByScenes : public Common::UnaryFunction<const Resource*, bool> {
|
||||
uint32 _sceneId1, _sceneId2;
|
||||
ResourceNotEqualByScenes(uint32 sceneId1, uint32 sceneId2) : _sceneId1(sceneId1), _sceneId2(sceneId2) {}
|
||||
bool operator()(const Resource *resource) const {
|
||||
return resource->_tag != _sceneId1 && resource->_tag != _sceneId2;
|
||||
}
|
||||
};
|
||||
|
||||
Resource *getResource(uint32 resId);
|
||||
void unloadResource(Resource *resource);
|
||||
|
||||
|
|
|
@ -22,12 +22,15 @@
|
|||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "engines/util.h"
|
||||
#include "graphics/palette.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// SpriteDecompressQueue
|
||||
|
||||
SpriteDecompressQueue::SpriteDecompressQueue() {
|
||||
SpriteDecompressQueue::SpriteDecompressQueue(Screen *screen)
|
||||
: _screen(screen) {
|
||||
}
|
||||
|
||||
SpriteDecompressQueue::~SpriteDecompressQueue() {
|
||||
|
@ -56,80 +59,7 @@ void SpriteDecompressQueue::decompressAll() {
|
|||
}
|
||||
|
||||
void SpriteDecompressQueue::decompress(SpriteDecompressQueueItem *item) {
|
||||
byte *src = item->_compressedPixels;
|
||||
Graphics::Surface *dstSurface = item->_surface;
|
||||
int dstSize = item->_dimensions._width * item->_dimensions._height;
|
||||
int processedSize = 0;
|
||||
int xincr, x, xstart;
|
||||
int yincr, y;
|
||||
|
||||
// Safeguard
|
||||
if (item->_dimensions._width > item->_surface->w ||
|
||||
item->_dimensions._height > item->_surface->h) {
|
||||
debug("Incorrect frame dimensions (%d, %d <> %d, %d)",
|
||||
item->_dimensions._width, item->_dimensions._height,
|
||||
item->_surface->w, item->_surface->h);
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->_flags & 1) {
|
||||
x = xstart = item->_dimensions._width - 1;
|
||||
xincr = -1;
|
||||
} else {
|
||||
x = xstart = 0;
|
||||
xincr = 1;
|
||||
}
|
||||
|
||||
if (item->_flags & 2) {
|
||||
y = item->_dimensions._height - 1;
|
||||
yincr = -1;
|
||||
} else {
|
||||
y = 0;
|
||||
yincr = 1;
|
||||
}
|
||||
|
||||
byte *dst = (byte*)dstSurface->getBasePtr(x, y);
|
||||
|
||||
while (processedSize < dstSize) {
|
||||
int16 op = READ_LE_UINT16(src);
|
||||
src += 2;
|
||||
if (op & 0x8000) {
|
||||
int runCount = (op & 0x7FFF) + 1;
|
||||
processedSize += runCount;
|
||||
uint16 runColor = READ_LE_UINT16(src);
|
||||
src += 2;
|
||||
while (runCount--) {
|
||||
WRITE_LE_UINT16(dst, runColor);
|
||||
x += xincr;
|
||||
if (x >= item->_dimensions._width || x < 0) {
|
||||
x = xstart;
|
||||
y += yincr;
|
||||
dst = (byte*)dstSurface->getBasePtr(x, y);
|
||||
} else {
|
||||
dst += 2 * xincr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int copyCount = op + 1;
|
||||
processedSize += copyCount;
|
||||
while (copyCount--) {
|
||||
uint16 color = READ_LE_UINT16(src);
|
||||
src += 2;
|
||||
WRITE_LE_UINT16(dst, color);
|
||||
x += xincr;
|
||||
if (x >= item->_dimensions._width || x < 0) {
|
||||
x = xstart;
|
||||
y += yincr;
|
||||
dst = (byte*)dstSurface->getBasePtr(x, y);
|
||||
} else {
|
||||
dst += 2 * xincr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*item->_drawFlags &= ~1;
|
||||
|
||||
_screen->decompressSprite(item);
|
||||
}
|
||||
|
||||
// SpriteDrawQueue
|
||||
|
@ -258,7 +188,7 @@ bool SpriteDrawQueue::calcItemRect(SpriteDrawQueueItem *item, Common::Rect &srcR
|
|||
*/
|
||||
|
||||
// Check if the sprite is on-screen
|
||||
if (dstRect.left >= 640 || dstRect.right <= 0 || dstRect.top >= 480 || dstRect.bottom <= 0)
|
||||
if (dstRect.left >= _screen->getScreenWidth() || dstRect.right <= 0 || dstRect.top >= _screen->getScreenHeight() || dstRect.bottom <= 0)
|
||||
return false;
|
||||
|
||||
// Clip the sprite rect if neccessary
|
||||
|
@ -273,14 +203,14 @@ bool SpriteDrawQueue::calcItemRect(SpriteDrawQueueItem *item, Common::Rect &srcR
|
|||
dstRect.top = 0;
|
||||
}
|
||||
|
||||
if (dstRect.right > 640) {
|
||||
srcRect.right += 100 * (640 - dstRect.right) / item->_scale;
|
||||
dstRect.right = 640;
|
||||
if (dstRect.right > _screen->getScreenWidth()) {
|
||||
srcRect.right += 100 * (_screen->getScreenWidth() - dstRect.right) / item->_scale;
|
||||
dstRect.right = _screen->getScreenWidth();
|
||||
}
|
||||
|
||||
if (dstRect.bottom > 480) {
|
||||
srcRect.bottom += 100 * (480 - dstRect.bottom) / item->_scale;
|
||||
dstRect.bottom = 480;
|
||||
if (dstRect.bottom > _screen->getScreenHeight()) {
|
||||
srcRect.bottom += 100 * (_screen->getScreenHeight() - dstRect.bottom) / item->_scale;
|
||||
dstRect.bottom = _screen->getScreenHeight();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -288,13 +218,24 @@ bool SpriteDrawQueue::calcItemRect(SpriteDrawQueueItem *item, Common::Rect &srcR
|
|||
|
||||
// Screen
|
||||
|
||||
Screen::Screen(IllusionsEngine *vm)
|
||||
Screen::Screen(IllusionsEngine *vm, int16 width, int16 height, int bpp)
|
||||
: _vm(vm), _colorKey2(0) {
|
||||
_displayOn = true;
|
||||
_backSurface = allocSurface(640, 480);
|
||||
_decompressQueue = new SpriteDecompressQueue();
|
||||
_decompressQueue = new SpriteDecompressQueue(this);
|
||||
_drawQueue = new SpriteDrawQueue(this);
|
||||
_colorKey1 = 0xF800 | 0x1F;
|
||||
if (bpp == 8) {
|
||||
initGraphics(width, height, false);
|
||||
} else {
|
||||
Graphics::PixelFormat pixelFormat16(2, 5, 6, 5, 0, 11, 5, 0, 0);
|
||||
initGraphics(width, height, true, &pixelFormat16);
|
||||
}
|
||||
|
||||
_backSurface = allocSurface(width, height);
|
||||
|
||||
_needRefreshPalette = false;
|
||||
memset(_mainPalette, 0, sizeof(_mainPalette));
|
||||
|
||||
}
|
||||
|
||||
Screen::~Screen() {
|
||||
|
@ -336,7 +277,295 @@ void Screen::updateSprites() {
|
|||
g_system->copyRectToScreen((byte*)_backSurface->getBasePtr(0, 0), _backSurface->pitch, 0, 0, _backSurface->w, _backSurface->h);
|
||||
}
|
||||
|
||||
void Screen::decompressSprite(SpriteDecompressQueueItem *item) {
|
||||
switch (_backSurface->format.bytesPerPixel) {
|
||||
case 1:
|
||||
decompressSprite8(item);
|
||||
break;
|
||||
case 2:
|
||||
decompressSprite16(item);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::drawSurface(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags) {
|
||||
switch (_backSurface->format.bytesPerPixel) {
|
||||
case 1:
|
||||
drawSurface8(dstRect, surface, srcRect, scale, flags);
|
||||
break;
|
||||
case 2:
|
||||
drawSurface16(dstRect, surface, srcRect, scale, flags);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::setPalette(byte *colors, uint start, uint count) {
|
||||
byte *dstPal = &_mainPalette[3 * (start - 1)];
|
||||
for (uint i = 0; i < count; ++i) {
|
||||
*dstPal++ = *colors++;
|
||||
*dstPal++ = *colors++;
|
||||
*dstPal++ = *colors++;
|
||||
++colors;
|
||||
}
|
||||
// TODO Build colorTransTbl
|
||||
_needRefreshPalette = true;
|
||||
}
|
||||
|
||||
void Screen::getPalette(byte *colors) {
|
||||
byte *srcPal = _mainPalette;
|
||||
for (uint i = 0; i < 256; ++i) {
|
||||
*colors++ = *srcPal++;
|
||||
*colors++ = *srcPal++;
|
||||
*colors++ = *srcPal++;
|
||||
++colors;
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::updatePalette() {
|
||||
if (_needRefreshPalette) {
|
||||
// TODO Update fader palette
|
||||
setSystemPalette(_mainPalette);
|
||||
_needRefreshPalette = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::setSystemPalette(byte *palette) {
|
||||
g_system->getPaletteManager()->setPalette(palette, 0, 256);
|
||||
}
|
||||
|
||||
void Screen::decompressSprite8(SpriteDecompressQueueItem *item) {
|
||||
byte *src = item->_compressedPixels;
|
||||
Graphics::Surface *dstSurface = item->_surface;
|
||||
int dstSize = item->_dimensions._width * item->_dimensions._height;
|
||||
int processedSize = 0;
|
||||
int xincr, x, xstart;
|
||||
int yincr, y;
|
||||
|
||||
*item->_drawFlags &= ~1;
|
||||
|
||||
// Safeguard
|
||||
if (item->_dimensions._width > item->_surface->w ||
|
||||
item->_dimensions._height > item->_surface->h) {
|
||||
debug("Incorrect frame dimensions (%d, %d <> %d, %d)",
|
||||
item->_dimensions._width, item->_dimensions._height,
|
||||
item->_surface->w, item->_surface->h);
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->_flags & 1) {
|
||||
x = xstart = item->_dimensions._width - 1;
|
||||
xincr = -1;
|
||||
} else {
|
||||
x = xstart = 0;
|
||||
xincr = 1;
|
||||
}
|
||||
|
||||
if (item->_flags & 2) {
|
||||
y = item->_dimensions._height - 1;
|
||||
yincr = -1;
|
||||
} else {
|
||||
y = 0;
|
||||
yincr = 1;
|
||||
}
|
||||
|
||||
byte *dst = (byte*)dstSurface->getBasePtr(x, y);
|
||||
|
||||
while (processedSize < dstSize) {
|
||||
byte op = *src++;
|
||||
if (op & 0x80) {
|
||||
int runCount = (op & 0x7F) + 1;
|
||||
processedSize += runCount;
|
||||
byte runColor = *src++;
|
||||
while (runCount--) {
|
||||
*dst = runColor;
|
||||
x += xincr;
|
||||
if (x >= item->_dimensions._width || x < 0) {
|
||||
x = xstart;
|
||||
y += yincr;
|
||||
dst = (byte*)dstSurface->getBasePtr(x, y);
|
||||
} else {
|
||||
dst += xincr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int copyCount = op + 1;
|
||||
processedSize += copyCount;
|
||||
while (copyCount--) {
|
||||
byte color = *src++;
|
||||
*dst = color;
|
||||
x += xincr;
|
||||
if (x >= item->_dimensions._width || x < 0) {
|
||||
x = xstart;
|
||||
y += yincr;
|
||||
dst = (byte*)dstSurface->getBasePtr(x, y);
|
||||
} else {
|
||||
dst += xincr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Screen::drawSurface8(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags) {
|
||||
drawSurface81(dstRect.left, dstRect.top, surface, srcRect);
|
||||
/*
|
||||
if (scale == 100) {
|
||||
drawSurface81(dstRect.left, dstRect.top, surface, srcRect);
|
||||
} else {
|
||||
drawSurface82(dstRect, surface, srcRect);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Screen::drawSurface81(int16 destX, int16 destY, Graphics::Surface *surface, Common::Rect &srcRect) {
|
||||
// Unscaled
|
||||
const int16 w = srcRect.width();
|
||||
const int16 h = srcRect.height();
|
||||
for (int16 yc = 0; yc < h; ++yc) {
|
||||
byte *src = (byte*)surface->getBasePtr(srcRect.left, srcRect.top + yc);
|
||||
byte *dst = (byte*)_backSurface->getBasePtr(destX, destY + yc);
|
||||
for (int16 xc = 0; xc < w; ++xc) {
|
||||
byte pixel = *src++;
|
||||
if (pixel != 0)
|
||||
*dst = pixel;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::drawSurface82(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect) {
|
||||
// Scaled
|
||||
const int dstWidth = dstRect.width(), dstHeight = dstRect.height();
|
||||
const int srcWidth = srcRect.width(), srcHeight = srcRect.height();
|
||||
const int errYStart = srcHeight / dstHeight;
|
||||
const int errYIncr = srcHeight % dstHeight;
|
||||
const int midY = dstHeight / 2;
|
||||
const int errXStart = srcWidth / dstWidth;
|
||||
const int errXIncr = srcWidth % dstWidth;
|
||||
const int midX = dstWidth / 2;
|
||||
int h = dstHeight, errY = 0, skipY, srcY = srcRect.top;
|
||||
byte *dst = (byte*)_backSurface->getBasePtr(dstRect.left, dstRect.top);
|
||||
skipY = (dstHeight < srcHeight) ? 0 : dstHeight / (2*srcHeight) + 1;
|
||||
h -= skipY;
|
||||
while (h-- > 0) {
|
||||
int w = dstWidth, errX = 0, skipX;
|
||||
skipX = (dstWidth < srcWidth) ? 0 : dstWidth / (2*srcWidth) + 1;
|
||||
w -= skipX;
|
||||
byte *src = (byte*)surface->getBasePtr(srcRect.left, srcY);
|
||||
byte *dstRow = dst;
|
||||
while (w-- > 0) {
|
||||
byte pixel = *src;
|
||||
if (pixel != 0) {
|
||||
*dstRow = pixel;
|
||||
}
|
||||
++dstRow;
|
||||
src += errXStart;
|
||||
errX += errXIncr;
|
||||
if (errX >= dstWidth) {
|
||||
errX -= dstWidth;
|
||||
++src;
|
||||
}
|
||||
}
|
||||
while (skipX-- > 0) {
|
||||
byte pixel = *src;
|
||||
if (pixel != 0)
|
||||
*dstRow = pixel;
|
||||
++src;
|
||||
++dstRow;
|
||||
}
|
||||
dst += _backSurface->pitch;
|
||||
srcY += errYStart;
|
||||
errY += errYIncr;
|
||||
if (errY >= dstHeight) {
|
||||
errY -= dstHeight;
|
||||
++srcY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::decompressSprite16(SpriteDecompressQueueItem *item) {
|
||||
byte *src = item->_compressedPixels;
|
||||
Graphics::Surface *dstSurface = item->_surface;
|
||||
int dstSize = item->_dimensions._width * item->_dimensions._height;
|
||||
int processedSize = 0;
|
||||
int xincr, x, xstart;
|
||||
int yincr, y;
|
||||
|
||||
*item->_drawFlags &= ~1;
|
||||
|
||||
// Safeguard
|
||||
if (item->_dimensions._width > item->_surface->w ||
|
||||
item->_dimensions._height > item->_surface->h) {
|
||||
debug("Incorrect frame dimensions (%d, %d <> %d, %d)",
|
||||
item->_dimensions._width, item->_dimensions._height,
|
||||
item->_surface->w, item->_surface->h);
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->_flags & 1) {
|
||||
x = xstart = item->_dimensions._width - 1;
|
||||
xincr = -1;
|
||||
} else {
|
||||
x = xstart = 0;
|
||||
xincr = 1;
|
||||
}
|
||||
|
||||
if (item->_flags & 2) {
|
||||
y = item->_dimensions._height - 1;
|
||||
yincr = -1;
|
||||
} else {
|
||||
y = 0;
|
||||
yincr = 1;
|
||||
}
|
||||
|
||||
byte *dst = (byte*)dstSurface->getBasePtr(x, y);
|
||||
|
||||
while (processedSize < dstSize) {
|
||||
int16 op = READ_LE_UINT16(src);
|
||||
src += 2;
|
||||
if (op & 0x8000) {
|
||||
int runCount = (op & 0x7FFF) + 1;
|
||||
processedSize += runCount;
|
||||
uint16 runColor = READ_LE_UINT16(src);
|
||||
src += 2;
|
||||
while (runCount--) {
|
||||
WRITE_LE_UINT16(dst, runColor);
|
||||
x += xincr;
|
||||
if (x >= item->_dimensions._width || x < 0) {
|
||||
x = xstart;
|
||||
y += yincr;
|
||||
dst = (byte*)dstSurface->getBasePtr(x, y);
|
||||
} else {
|
||||
dst += 2 * xincr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int copyCount = op + 1;
|
||||
processedSize += copyCount;
|
||||
while (copyCount--) {
|
||||
uint16 color = READ_LE_UINT16(src);
|
||||
src += 2;
|
||||
WRITE_LE_UINT16(dst, color);
|
||||
x += xincr;
|
||||
if (x >= item->_dimensions._width || x < 0) {
|
||||
x = xstart;
|
||||
y += yincr;
|
||||
dst = (byte*)dstSurface->getBasePtr(x, y);
|
||||
} else {
|
||||
dst += 2 * xincr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Screen::drawSurface16(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags) {
|
||||
if (scale == 100) {
|
||||
if (flags & 1)
|
||||
drawSurface10(dstRect.left, dstRect.top, surface, srcRect, _colorKey2);
|
||||
|
|
|
@ -44,7 +44,7 @@ struct SpriteDecompressQueueItem {
|
|||
|
||||
class SpriteDecompressQueue {
|
||||
public:
|
||||
SpriteDecompressQueue();
|
||||
SpriteDecompressQueue(Screen *screen);
|
||||
~SpriteDecompressQueue();
|
||||
void insert(byte *drawFlags, uint32 flags, uint32 field8, WidthHeight &dimensions,
|
||||
byte *compressedPixels, Graphics::Surface *surface);
|
||||
|
@ -52,6 +52,7 @@ public:
|
|||
protected:
|
||||
typedef Common::List<SpriteDecompressQueueItem*> SpriteDecompressQueueList;
|
||||
typedef SpriteDecompressQueueList::iterator SpriteDecompressQueueListIterator;
|
||||
Screen *_screen;
|
||||
SpriteDecompressQueueList _queue;
|
||||
void decompress(SpriteDecompressQueueItem *item);
|
||||
};
|
||||
|
@ -96,9 +97,11 @@ protected:
|
|||
bool calcItemRect(SpriteDrawQueueItem *item, Common::Rect &srcRect, Common::Rect &dstRect);
|
||||
};
|
||||
|
||||
// TODO Split into two classes (8bit and 16bit)?
|
||||
|
||||
class Screen {
|
||||
public:
|
||||
Screen(IllusionsEngine *vm);
|
||||
Screen(IllusionsEngine *vm, int16 width, int16 height, int bpp);
|
||||
~Screen();
|
||||
Graphics::Surface *allocSurface(int16 width, int16 height);
|
||||
Graphics::Surface *allocSurface(SurfInfo &surfInfo);
|
||||
|
@ -106,11 +109,13 @@ public:
|
|||
void setDisplayOn(bool isOn);
|
||||
uint16 getColorKey2();
|
||||
void updateSprites();
|
||||
void decompressSprite(SpriteDecompressQueueItem *item);
|
||||
void drawSurface(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags);
|
||||
void drawSurface10(int16 destX, int16 destY, Graphics::Surface *surface, Common::Rect &srcRect, uint16 colorKey);
|
||||
void drawSurface11(int16 destX, int16 destY, Graphics::Surface *surface, Common::Rect &srcRect);
|
||||
void drawSurface20(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, uint16 colorKey);
|
||||
void drawSurface21(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect);
|
||||
void setPalette(byte *colors, uint start, uint count);
|
||||
void getPalette(byte *colors);
|
||||
void updatePalette();
|
||||
int16 getScreenWidth() const { return _backSurface->w; }
|
||||
int16 getScreenHeight() const { return _backSurface->h; }
|
||||
public:
|
||||
IllusionsEngine *_vm;
|
||||
bool _displayOn;
|
||||
|
@ -119,6 +124,23 @@ public:
|
|||
SpriteDecompressQueue *_decompressQueue;
|
||||
SpriteDrawQueue *_drawQueue;
|
||||
Graphics::Surface *_backSurface;
|
||||
|
||||
bool _needRefreshPalette;
|
||||
byte _mainPalette[768];
|
||||
|
||||
void setSystemPalette(byte *palette);
|
||||
|
||||
void decompressSprite8(SpriteDecompressQueueItem *item);
|
||||
void drawSurface8(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags);
|
||||
void drawSurface81(int16 destX, int16 destY, Graphics::Surface *surface, Common::Rect &srcRect);
|
||||
void drawSurface82(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect);
|
||||
|
||||
void decompressSprite16(SpriteDecompressQueueItem *item);
|
||||
void drawSurface16(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags);
|
||||
void drawSurface10(int16 destX, int16 destY, Graphics::Surface *surface, Common::Rect &srcRect, uint16 colorKey);
|
||||
void drawSurface11(int16 destX, int16 destY, Graphics::Surface *surface, Common::Rect &srcRect);
|
||||
void drawSurface20(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, uint16 colorKey);
|
||||
void drawSurface21(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/illusions_bbdou.h"
|
||||
#include "illusions/scriptopcodes_bbdou.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
|
|
|
@ -125,4 +125,4 @@ protected:
|
|||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_SCRIPTOPCODES_H
|
||||
#endif // ILLUSIONS_SCRIPTOPCODES_BBDOU_H
|
||||
|
|
811
engines/illusions/scriptopcodes_duckman.cpp
Normal file
811
engines/illusions/scriptopcodes_duckman.cpp
Normal file
|
@ -0,0 +1,811 @@
|
|||
/* 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 "illusions/illusions_duckman.h"
|
||||
#include "illusions/scriptopcodes_duckman.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "illusions/scriptman.h"
|
||||
#include "illusions/scriptresource.h"
|
||||
#include "illusions/scriptthread.h"
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/talkresource.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// ScriptOpcodes_Duckman
|
||||
|
||||
ScriptOpcodes_Duckman::ScriptOpcodes_Duckman(IllusionsEngine_Duckman *vm)
|
||||
: ScriptOpcodes(vm), _vm(vm) {
|
||||
initOpcodes();
|
||||
}
|
||||
|
||||
ScriptOpcodes_Duckman::~ScriptOpcodes_Duckman() {
|
||||
freeOpcodes();
|
||||
}
|
||||
|
||||
typedef Common::Functor2Mem<ScriptThread*, OpCall&, void, ScriptOpcodes_Duckman> ScriptOpcodeI;
|
||||
#define OPCODE(op, func) \
|
||||
_opcodes[op] = new ScriptOpcodeI(this, &ScriptOpcodes_Duckman::func); \
|
||||
_opcodeNames[op] = #func;
|
||||
|
||||
void ScriptOpcodes_Duckman::initOpcodes() {
|
||||
// First clear everything
|
||||
for (uint i = 0; i < 256; ++i)
|
||||
_opcodes[i] = 0;
|
||||
OPCODE(2, opSuspend);
|
||||
OPCODE(3, opYield);
|
||||
OPCODE(4, opTerminate);
|
||||
OPCODE(5, opJump);
|
||||
OPCODE(6, opStartScriptThread);
|
||||
OPCODE(7, opStartTimerThread);
|
||||
OPCODE(9, opNotifyThread);
|
||||
OPCODE(10, opSuspendThread);
|
||||
OPCODE(18, opEnterScene18);
|
||||
OPCODE(20, opChangeScene);
|
||||
OPCODE(24, opEnterScene24);
|
||||
OPCODE(25, opLeaveScene24);
|
||||
OPCODE(38, opStartFade);
|
||||
OPCODE(39, opSetDisplay);
|
||||
OPCODE(49, opPlaceActor);
|
||||
OPCODE(52, opStartSequenceActor);
|
||||
OPCODE(56, opStartTalkThread);
|
||||
OPCODE(57, opAppearActor);
|
||||
OPCODE(58, opDisappearActor);
|
||||
OPCODE(59, opActivateObject);
|
||||
OPCODE(60, opDeactivateObject);
|
||||
OPCODE(61, opSetDefaultSequence);
|
||||
OPCODE(66, opPlayVideo);
|
||||
OPCODE(69, opRunSpecialCode);
|
||||
OPCODE(72, opStartSound);
|
||||
OPCODE(75, opStopSound);
|
||||
OPCODE(76, opStartMidiMusic);
|
||||
OPCODE(77, opStopMidiMusic);
|
||||
OPCODE(80, opAddMenuChoice);
|
||||
OPCODE(81, opDisplayMenu);
|
||||
OPCODE(82, opSwitchMenuChoice);
|
||||
OPCODE(84, opResetGame);
|
||||
OPCODE(87, opDeactivateButton);
|
||||
OPCODE(88, opActivateButton);
|
||||
OPCODE(96, opIncBlockCounter);
|
||||
OPCODE(104, opJumpIf);
|
||||
OPCODE(106, opNot);
|
||||
OPCODE(107, opAnd);
|
||||
OPCODE(108, opOr);
|
||||
OPCODE(109, opGetProperty);
|
||||
OPCODE(110, opCompareBlockCounter);
|
||||
OPCODE(126, opDebug126);
|
||||
#if 0
|
||||
// Register opcodes
|
||||
OPCODE(8, opStartTempScriptThread);
|
||||
OPCODE(14, opSetThreadSceneId);
|
||||
OPCODE(15, opEndTalkThreads);
|
||||
OPCODE(17, opUnloadResource);
|
||||
OPCODE(20, opEnterScene);
|
||||
OPCODE(26, opStartModalScene);
|
||||
OPCODE(27, opExitModalScene);
|
||||
OPCODE(30, opEnterCloseUpScene);
|
||||
OPCODE(31, opExitCloseUpScene);
|
||||
OPCODE(32, opPanCenterObject);
|
||||
OPCODE(34, opPanToObject);
|
||||
OPCODE(35, opPanToNamedPoint);
|
||||
OPCODE(36, opPanToPoint);
|
||||
OPCODE(37, opPanStop);
|
||||
OPCODE(43, opClearBlockCounter);
|
||||
OPCODE(45, opSetProperty);
|
||||
OPCODE(47, opFaceActor);
|
||||
OPCODE(48, opFaceActorToObject);
|
||||
OPCODE(51, opStartMoveActor);
|
||||
OPCODE(53, opSetActorToNamedPoint);
|
||||
OPCODE(63, opSetSelectSfx);
|
||||
OPCODE(64, opSetMoveSfx);
|
||||
OPCODE(65, opSetDenySfx);
|
||||
OPCODE(66, opSetAdjustUpSfx);
|
||||
OPCODE(67, opSetAdjustDnSfx);
|
||||
OPCODE(78, opStackPushRandom);
|
||||
OPCODE(79, opIfLte);
|
||||
OPCODE(104, opIsPrevSceneId);
|
||||
OPCODE(105, opIsCurrentSceneId);
|
||||
OPCODE(106, opIsActiveSceneId);
|
||||
OPCODE(146, opStackPop);
|
||||
OPCODE(147, opStackDup);
|
||||
OPCODE(148, opLoadSpecialCodeModule);
|
||||
OPCODE(160, opStopActor);
|
||||
OPCODE(161, opSetActorUsePan);
|
||||
OPCODE(168, opStartAbortableThread);
|
||||
OPCODE(169, opKillThread);
|
||||
OPCODE(175, opSetSceneIdThreadId);
|
||||
OPCODE(176, opStackPush0);
|
||||
OPCODE(177, opSetFontId);
|
||||
OPCODE(178, opAddMenuKey);
|
||||
OPCODE(179, opChangeSceneAll);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef OPCODE
|
||||
|
||||
void ScriptOpcodes_Duckman::freeOpcodes() {
|
||||
for (uint i = 0; i < 256; ++i)
|
||||
delete _opcodes[i];
|
||||
}
|
||||
|
||||
// Opcodes
|
||||
|
||||
void ScriptOpcodes_Duckman::opSuspend(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._result = kTSSuspend;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opYield(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._result = kTSYield;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opTerminate(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._result = kTSTerminate;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opJump(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(jumpOffs);
|
||||
opCall._deltaOfs += jumpOffs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->startScriptThread(threadId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartTimerThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(isAbortable);
|
||||
ARG_INT16(duration);
|
||||
ARG_INT16(maxDuration);
|
||||
if (maxDuration)
|
||||
duration += _vm->getRandom(maxDuration);
|
||||
|
||||
//duration = 1;//DEBUG Speeds up things
|
||||
duration = 5;
|
||||
|
||||
if (isAbortable)
|
||||
_vm->startAbortableTimerThread(duration, opCall._threadId);
|
||||
else
|
||||
_vm->startTimerThread(duration, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opNotifyThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->_threads->notifyId(threadId);
|
||||
_vm->_threads->notifyTimerThreads(threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSuspendThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->_threads->suspendId(threadId);
|
||||
_vm->_threads->suspendTimerThreads(threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opEnterScene18(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->enterScene(sceneId, 0);
|
||||
}
|
||||
|
||||
static uint dsceneId = 0x00010008, dthreadId = 0x00020029;
|
||||
|
||||
void ScriptOpcodes_Duckman::opChangeScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->_input->discardButtons(0xFFFF);
|
||||
|
||||
//DEBUG
|
||||
if (dsceneId) {
|
||||
sceneId = dsceneId;
|
||||
threadId = dthreadId;
|
||||
dsceneId = 0;
|
||||
}
|
||||
|
||||
if (_vm->_scriptResource->_properties.get(31)) {
|
||||
_vm->changeScene(0x10002, 0x20001, opCall._callerThreadId);
|
||||
} else {
|
||||
_vm->changeScene(sceneId, threadId, opCall._callerThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opEnterScene24(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_input->discardButtons(0xFFFF);
|
||||
_vm->enterPause(_vm->getCurrentScene(), opCall._callerThreadId);
|
||||
_vm->enterScene(sceneId, 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opLeaveScene24(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_input->discardButtons(0xFFFF);
|
||||
_vm->dumpCurrSceneFiles(_vm->getCurrentScene(), opCall._callerThreadId);
|
||||
_vm->exitScene();
|
||||
_vm->leavePause(_vm->getCurrentScene(), opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartFade(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(arg1);
|
||||
ARG_INT16(arg2);
|
||||
ARG_INT16(arg3);
|
||||
ARG_INT16(arg4);
|
||||
ARG_INT16(arg5);
|
||||
// TODO
|
||||
|
||||
//DEBUG Resume calling thread, later done when the fading is finished
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetDisplay(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(flag);
|
||||
_vm->_screen->setDisplayOn(flag != 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPlaceActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(sequenceId);
|
||||
ARG_UINT32(namedPointId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
uint32 actorTypeId = _vm->getObjectActorTypeId(objectId);
|
||||
_vm->_controls->placeActor(actorTypeId, pos, sequenceId, objectId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartSequenceActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(sequenceId);
|
||||
// NOTE Skipped checking for stalled sequence, not sure if needed
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->startSequenceActor(sequenceId, 2, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(talkId);
|
||||
ARG_UINT32(sequenceId1);
|
||||
ARG_UINT32(sequenceId2);
|
||||
_vm->startTalkThread(objectId, talkId, sequenceId1, sequenceId2, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opAppearActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
if (!control) {
|
||||
Common::Point pos = _vm->getNamedPointPosition(0x70001);
|
||||
_vm->_controls->placeActor(0x50001, pos, 0x60001, objectId, 0);
|
||||
control = _vm->_dict->getObjectControl(objectId);
|
||||
}
|
||||
control->appearActor();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDisappearActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->disappearActor();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opActivateObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
if (control)
|
||||
control->activateObject();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDeactivateObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->deactivateObject();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetDefaultSequence(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(defaultSequenceId);
|
||||
ARG_UINT32(sequenceId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->_actor->_defaultSequences.set(sequenceId, defaultSequenceId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPlayVideo(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
// NOTE This has no attached objectId or priority
|
||||
// TODO _vm->playVideo(videoId, objectId, value, opCall._threadId);
|
||||
|
||||
//DEBUG Resume calling thread, later done by the video player
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(specialCodeId);
|
||||
//TODO _vm->_specialCode->run(specialCodeId, opCall);
|
||||
//DEBUG Resume calling thread, later done by the special code
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartSound(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(volume);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->startSound(soundEffectId, volume, pan);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStopSound(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->stopSound(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartMidiMusic(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(musicId);
|
||||
// TODO _vm->playMidiMusic(musicId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStopMidiMusic(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// TODO _vm->stopMidiMusic();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(jumpOffs);
|
||||
ARG_INT16(endMarker);
|
||||
_vm->_stack->push(endMarker);
|
||||
_vm->_stack->push(jumpOffs);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDisplayMenu(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(unk1);
|
||||
ARG_UINT32(menuId);
|
||||
ARG_UINT32(unk2);
|
||||
// TODO _vm->_shellMgr->displayMenu(_vm->_stack->topPtr(), &_vm->_menuChoiceOfs, menuId, unk1, unk2, opCall._callerThreadId);
|
||||
// Remove menu choices from the stack
|
||||
do {
|
||||
_vm->_stack->pop();
|
||||
} while (_vm->_stack->pop() == 0);
|
||||
|
||||
//DEBUG Resume calling thread, later done by the video player
|
||||
_vm->notifyThreadId(opCall._callerThreadId);
|
||||
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSwitchMenuChoice(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_menuChoiceOfs = 156; // DEBUG Chose "Start game"
|
||||
|
||||
opCall._deltaOfs += _vm->_menuChoiceOfs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opResetGame(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->reset();
|
||||
_vm->_input->activateButton(0xFFFF);
|
||||
// TODO _vm->stopMusic();
|
||||
// TODO _vm->_gameStates->clear();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(button)
|
||||
_vm->_input->deactivateButton(button);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opActivateButton(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(button)
|
||||
_vm->_input->activateButton(button);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
byte value = _vm->_scriptResource->_blockCounters.get(index) + 1;
|
||||
if (value <= 63)
|
||||
_vm->_scriptResource->_blockCounters.set(index, value);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opJumpIf(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(jumpOffs);
|
||||
int16 value = _vm->_stack->pop();
|
||||
if (value == 0)
|
||||
opCall._deltaOfs += jumpOffs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opNot(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value = _vm->_stack->pop();
|
||||
_vm->_stack->push(value != 0 ? 0 : 1);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opAnd(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value1 = _vm->_stack->pop();
|
||||
int16 value2 = _vm->_stack->pop();
|
||||
_vm->_stack->push(value1 & value2);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opOr(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value1 = _vm->_stack->pop();
|
||||
int16 value2 = _vm->_stack->pop();
|
||||
_vm->_stack->push(value1 | value2);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opGetProperty(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(propertyId)
|
||||
bool value = _vm->_scriptResource->_properties.get(propertyId);
|
||||
_vm->_stack->push(value ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opCompareBlockCounter(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
ARG_INT16(compareOp);
|
||||
ARG_INT16(rvalue);
|
||||
int16 lvalue = _vm->_scriptResource->_blockCounters.get(index);
|
||||
bool compareResult = false;
|
||||
switch (compareOp) {
|
||||
case 1:
|
||||
compareResult = lvalue == rvalue;
|
||||
break;
|
||||
case 2:
|
||||
compareResult = lvalue != rvalue;
|
||||
break;
|
||||
case 3:
|
||||
compareResult = lvalue < rvalue;
|
||||
break;
|
||||
case 4:
|
||||
compareResult = lvalue > rvalue;
|
||||
break;
|
||||
case 5:
|
||||
compareResult = lvalue >= rvalue;
|
||||
break;
|
||||
case 6:
|
||||
compareResult = lvalue <= rvalue;
|
||||
break;
|
||||
}
|
||||
_vm->_stack->push(compareResult ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDebug126(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// NOTE Prints some debug text
|
||||
debug(1, "[DBG] %s", (char*)opCall._code);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartTempScriptThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(codeOffs);
|
||||
_vm->startTempScriptThread(opCall._code + codeOffs,
|
||||
opCall._threadId, scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetThreadSceneId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_threads->setThreadSceneId(opCall._callerThreadId, sceneId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opEndTalkThreads(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_threads->endTalkThreads();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opLoadResource(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(resourceId);
|
||||
// NOTE Skipped checking for stalled resources
|
||||
uint32 sceneId = _vm->getCurrentScene();
|
||||
_vm->_resSys->loadResource(resourceId, sceneId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opUnloadResource(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(resourceId);
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_resSys->unloadResourceById(resourceId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opEnterScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
uint scenesCount = _vm->_activeScenes.getActiveScenesCount();
|
||||
if (scenesCount > 0) {
|
||||
uint32 currSceneId;
|
||||
_vm->_activeScenes.getActiveSceneInfo(scenesCount, &currSceneId, 0);
|
||||
// TODO krnfileDump(currSceneId);
|
||||
}
|
||||
if (!_vm->enterScene(sceneId, opCall._callerThreadId))
|
||||
opCall._result = kTSTerminate;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartModalScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
ARG_UINT32(threadId);
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_input->discardButtons(0xFFFF);
|
||||
_vm->enterPause(opCall._callerThreadId);
|
||||
_vm->_talkItems->pauseByTag(_vm->getCurrentScene());
|
||||
_vm->enterScene(sceneId, opCall._callerThreadId);
|
||||
_vm->startScriptThread(threadId, 0,
|
||||
scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10);
|
||||
opCall._result = kTSSuspend;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opExitModalScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_input->discardButtons(0xFFFF);
|
||||
_vm->exitScene(opCall._callerThreadId);
|
||||
_vm->leavePause(opCall._callerThreadId);
|
||||
_vm->_talkItems->unpauseByTag(_vm->getCurrentScene());
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_input->discardButtons(0xFFFF);
|
||||
_vm->enterPause(opCall._callerThreadId);
|
||||
_vm->enterScene(sceneId, opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->exitScene(opCall._callerThreadId);
|
||||
_vm->leavePause(opCall._callerThreadId);
|
||||
opCall._result = kTSYield;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_UINT32(objectId);
|
||||
_vm->_camera->panCenterObject(objectId, speed);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanToObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
Common::Point pos = control->getActorPosition();
|
||||
_vm->_camera->panToPoint(pos, speed, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_UINT32(namedPointId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
_vm->_camera->panToPoint(pos, speed, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanToPoint(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_INT16(x);
|
||||
ARG_INT16(y);
|
||||
_vm->_camera->panToPoint(Common::Point(x, y), speed, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanStop(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_camera->stopPan();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opClearBlockCounter(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
_vm->_scriptResource->_blockCounters.set(index, 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetProperty(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(value);
|
||||
ARG_UINT32(propertyId);
|
||||
_vm->_scriptResource->_properties.set(propertyId, value != 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opFaceActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(facing);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->faceActor(facing);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opFaceActorToObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId1);
|
||||
ARG_UINT32(objectId2);
|
||||
Control *control1 = _vm->_dict->getObjectControl(objectId1);
|
||||
Control *control2 = _vm->_dict->getObjectControl(objectId2);
|
||||
Common::Point pos1 = control1->getActorPosition();
|
||||
Common::Point pos2 = control2->getActorPosition();
|
||||
uint facing;
|
||||
if (_vm->calcPointDirection(pos1, pos2, facing))
|
||||
control1->faceActor(facing);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(sequenceId);
|
||||
ARG_UINT32(namedPointId);
|
||||
// NOTE Skipped checking for stalled sequence, not sure if needed
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
control->startMoveActor(sequenceId, pos, opCall._callerThreadId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(namedPointId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
control->stopActor();
|
||||
control->setActorPosition(pos);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->setSelectSfx(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->setMoveSfx(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetDenySfx(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->setDenySfx(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetAdjustUpSfx(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->setAdjustUpSfx(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetAdjustDnSfx(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->setAdjustDnSfx(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStackPushRandom(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(maxValue);
|
||||
_vm->_stack->push(_vm->getRandom(maxValue) + 1);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opIfLte(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(rvalue);
|
||||
ARG_INT16(elseJumpOffs);
|
||||
int16 lvalue = _vm->_stack->pop();
|
||||
if (!(lvalue <= rvalue))
|
||||
opCall._deltaOfs += elseJumpOffs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_stack->push(_vm->_prevSceneId == sceneId ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_stack->push(_vm->getCurrentScene() == sceneId ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_stack->push(_vm->_activeScenes.isSceneActive(sceneId) ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStackPop(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_stack->pop();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStackDup(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value = _vm->_stack->peek();
|
||||
_vm->_stack->push(value);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opLoadSpecialCodeModule(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(specialCodeModuleId);
|
||||
_vm->_resSys->loadResource(specialCodeModuleId, 0, 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStopActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->stopActor();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetActorUsePan(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(usePan)
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->setActorUsePan(usePan);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartAbortableThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(codeOffs);
|
||||
ARG_INT16(skipOffs);
|
||||
_vm->startAbortableThread(opCall._code + codeOffs,
|
||||
opCall._code + skipOffs, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opKillThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->_threads->killThread(threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetSceneIdThreadId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->setSceneIdThreadId(sceneId, threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStackPush0(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_stack->push(0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetFontId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(fontId);
|
||||
_vm->setCurrFontId(fontId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(key);
|
||||
ARG_UINT32(threadId);
|
||||
// TODO _vm->addMenuKey(key, threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
ARG_UINT32(threadId);
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_input->discardButtons(0xFFFF);
|
||||
_vm->_prevSceneId = _vm->getCurrentScene();
|
||||
_vm->dumpActiveScenes(_vm->_globalSceneId, opCall._callerThreadId);
|
||||
_vm->enterScene(sceneId, opCall._callerThreadId);
|
||||
// TODO _vm->_gameStates->writeStates(_vm->_prevSceneId, sceneId, threadId);
|
||||
_vm->startAnonScriptThread(threadId, 0,
|
||||
scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Illusions
|
137
engines/illusions/scriptopcodes_duckman.h
Normal file
137
engines/illusions/scriptopcodes_duckman.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_SCRIPTOPCODES_DUCKMAN_H
|
||||
#define ILLUSIONS_SCRIPTOPCODES_DUCKMAN_H
|
||||
|
||||
#include "illusions/scriptopcodes.h"
|
||||
#include "common/func.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_Duckman;
|
||||
class ScriptThread;
|
||||
|
||||
class ScriptOpcodes_Duckman : public ScriptOpcodes {
|
||||
public:
|
||||
ScriptOpcodes_Duckman(IllusionsEngine_Duckman *vm);
|
||||
~ScriptOpcodes_Duckman();
|
||||
void initOpcodes();
|
||||
void freeOpcodes();
|
||||
protected:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
|
||||
// Opcodes
|
||||
|
||||
void opSuspend(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opYield(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opTerminate(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opJump(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opNotifyThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSuspendThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartTimerThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterScene18(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opChangeScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterScene24(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLeaveScene24(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartFade(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetDisplay(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPlaceActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartSequenceActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAppearActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDisappearActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opActivateObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDeactivateObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetDefaultSequence(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPlayVideo(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartSound(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStopSound(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartMidiMusic(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStopMidiMusic(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDisplayMenu(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSwitchMenuChoice(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opResetGame(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opActivateButton(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opJumpIf(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opNot(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAnd(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opOr(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opGetProperty(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opCompareBlockCounter(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDebug126(ScriptThread *scriptThread, OpCall &opCall);
|
||||
|
||||
#if 0
|
||||
void opStartTempScriptThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetThreadSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEndTalkThreads(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLoadResource(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opUnloadResource(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartModalScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opExitModalScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanToObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanToPoint(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanStop(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opClearBlockCounter(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetProperty(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opFaceActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opFaceActorToObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetDenySfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetAdjustUpSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetAdjustDnSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackPushRandom(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIfLte(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackPop(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackDup(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLoadSpecialCodeModule(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStopActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetActorUsePan(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartAbortableThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opKillThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetSceneIdThreadId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackPush0(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetFontId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall);
|
||||
#endif
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_SCRIPTOPCODES_DUCKMAN_H
|
|
@ -32,13 +32,14 @@ void ScriptResourceLoader::load(Resource *resource) {
|
|||
debug(2, "ScriptResourceLoader::load() Loading script %08X from %s...", resource->_resId, resource->_filename.c_str());
|
||||
|
||||
ScriptResource *scriptResource = new ScriptResource();
|
||||
scriptResource->load(resource->_data, resource->_dataSize);
|
||||
scriptResource->load(resource);
|
||||
|
||||
_vm->_scriptResource = scriptResource;
|
||||
|
||||
}
|
||||
|
||||
void ScriptResourceLoader::unload(Resource *resource) {
|
||||
delete _vm->_scriptResource;
|
||||
}
|
||||
|
||||
void ScriptResourceLoader::buildFilename(Resource *resource) {
|
||||
|
@ -153,14 +154,21 @@ bool TriggerObject::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &co
|
|||
return false;
|
||||
}
|
||||
|
||||
void TriggerObject::fixupProgInfosDuckman() {
|
||||
for (uint i = 0; i < _causesCount; ++i)
|
||||
_causes[i]._verbId &= 0xFFFF;
|
||||
}
|
||||
|
||||
// ProgInfo
|
||||
|
||||
ProgInfo::ProgInfo()
|
||||
: _triggerObjectsCount(0), _triggerObjects(0) {
|
||||
: _triggerObjectsCount(0), _triggerObjects(0),
|
||||
_resourcesCount(0), _resources(0) {
|
||||
}
|
||||
|
||||
ProgInfo::~ProgInfo() {
|
||||
delete[] _triggerObjects;
|
||||
delete[] _resources;
|
||||
}
|
||||
|
||||
char *debugW2I(byte *wstr) {
|
||||
|
@ -180,10 +188,15 @@ void ProgInfo::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
|||
_name = dataStart + stream.pos();
|
||||
stream.skip(128);
|
||||
_triggerObjectsCount = stream.readUint16LE();
|
||||
stream.skip(2); // Skip padding
|
||||
_resourcesCount = stream.readUint16LE();
|
||||
debug(2, "\nProgInfo::load() _id: %d; _unk: %d; _name: [%s]",
|
||||
_id, _unk, debugW2I(_name));
|
||||
uint32 triggerObjectsListOffs = stream.readUint32LE();
|
||||
if (_resourcesCount > 0) {
|
||||
_resources = new uint32[_resourcesCount];
|
||||
for (uint i = 0; i < _resourcesCount; ++i)
|
||||
_resources[i] = stream.readUint32LE();
|
||||
}
|
||||
if (_triggerObjectsCount > 0) {
|
||||
_triggerObjects = new TriggerObject[_triggerObjectsCount];
|
||||
for (uint i = 0; i < _triggerObjectsCount; ++i) {
|
||||
|
@ -202,6 +215,11 @@ bool ProgInfo::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId
|
|||
return false;
|
||||
}
|
||||
|
||||
void ProgInfo::getResources(uint &resourcesCount, uint32 *&resources) {
|
||||
resourcesCount = _resourcesCount;
|
||||
resources = _resources;
|
||||
}
|
||||
|
||||
TriggerObject *ProgInfo::findTriggerObject(uint32 objectId) {
|
||||
for (uint i = 0; i < _triggerObjectsCount; ++i)
|
||||
if (_triggerObjects[i]._objectId == objectId)
|
||||
|
@ -209,36 +227,67 @@ TriggerObject *ProgInfo::findTriggerObject(uint32 objectId) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ProgInfo::fixupProgInfosDuckman() {
|
||||
for (uint i = 0; i < _triggerObjectsCount; ++i)
|
||||
_triggerObjects[i].fixupProgInfosDuckman();
|
||||
}
|
||||
|
||||
// ScriptResource
|
||||
|
||||
ScriptResource::ScriptResource()
|
||||
: _codeOffsets(0) {
|
||||
: _codeOffsets(0), _objectMap(0) {
|
||||
}
|
||||
|
||||
ScriptResource::~ScriptResource() {
|
||||
delete[] _codeOffsets;
|
||||
delete[] _objectMap;
|
||||
}
|
||||
|
||||
void ScriptResource::load(byte *data, uint32 dataSize) {
|
||||
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
|
||||
void ScriptResource::load(Resource *resource) {
|
||||
_data = resource->_data;
|
||||
_dataSize = resource->_dataSize;
|
||||
|
||||
_data = data;
|
||||
_dataSize = dataSize;
|
||||
Common::MemoryReadStream stream(_data, _dataSize, DisposeAfterUse::NO);
|
||||
|
||||
uint32 objectMapOffs, progInfosOffs;
|
||||
_objectMapCount = 0;
|
||||
|
||||
if (resource->_gameId == kGameIdBBDOU) {
|
||||
progInfosOffs = 0x18;
|
||||
} else if (resource->_gameId == kGameIdDuckman) {
|
||||
for (uint i = 0; i < 27; ++i)
|
||||
_soundIds[i] = stream.readUint32LE();
|
||||
progInfosOffs = 0x8C;
|
||||
}
|
||||
|
||||
stream.skip(4); // Skip unused
|
||||
|
||||
// Read item counts
|
||||
uint propertiesCount = stream.readUint16LE();
|
||||
uint blockCountersCount = stream.readUint16LE();
|
||||
if (resource->_gameId == kGameIdDuckman)
|
||||
_objectMapCount = stream.readUint16LE();
|
||||
_codeCount = stream.readUint16LE();
|
||||
_progInfosCount = stream.readUint16LE();
|
||||
if (resource->_gameId == kGameIdDuckman)
|
||||
stream.readUint16LE();//Unused?
|
||||
|
||||
// Read item offsets
|
||||
uint32 propertiesOffs = stream.readUint32LE();
|
||||
uint32 blockCountersOffs = stream.readUint32LE();
|
||||
if (resource->_gameId == kGameIdDuckman)
|
||||
objectMapOffs = stream.readUint32LE();
|
||||
uint32 codeTblOffs = stream.readUint32LE();
|
||||
|
||||
debug(2, "ScriptResource::load() propertiesCount: %d; blockCountersCount: %d; _codeCount: %d; _progInfosCount: %d; _objectMapCount: %d",
|
||||
propertiesCount, blockCountersCount, _codeCount, _progInfosCount, _objectMapCount);
|
||||
debug(2, "ScriptResource::load() propertiesOffs: %08X; blockCountersOffs: %08X; codeTblOffs: %08X; objectMapOffs: %08X",
|
||||
propertiesOffs, blockCountersOffs, codeTblOffs, objectMapOffs);
|
||||
// Init properties
|
||||
_properties.init(propertiesCount, data + propertiesOffs);
|
||||
_properties.init(propertiesCount, _data + propertiesOffs);
|
||||
|
||||
// Init blockcounters
|
||||
_blockCounters.init(blockCountersCount, data + blockCountersOffs);
|
||||
_blockCounters.init(blockCountersCount, _data + blockCountersOffs);
|
||||
|
||||
_codeOffsets = new uint32[_codeCount];
|
||||
stream.seek(codeTblOffs);
|
||||
|
@ -247,16 +296,23 @@ void ScriptResource::load(byte *data, uint32 dataSize) {
|
|||
|
||||
_progInfos = new ProgInfo[_progInfosCount];
|
||||
for (uint i = 0; i < _progInfosCount; ++i) {
|
||||
stream.seek(0x18 + i * 4);
|
||||
stream.seek(progInfosOffs + i * 4);
|
||||
uint32 progInfoOffs = stream.readUint32LE();
|
||||
stream.seek(progInfoOffs);
|
||||
_progInfos[i].load(data, stream);
|
||||
_progInfos[i].load(_data, stream);
|
||||
}
|
||||
|
||||
debug(2, "ScriptResource::load() propertiesCount: %d; blockCountersCount: %d; _codeCount: %d; _progInfosCount: %d",
|
||||
propertiesCount, blockCountersCount, _codeCount, _progInfosCount);
|
||||
debug(2, "ScriptResource::load() propertiesOffs: %08X; blockCountersOffs: %08X; codeTblOffs: %08X",
|
||||
propertiesOffs, blockCountersOffs, codeTblOffs);
|
||||
if (_objectMapCount > 0) {
|
||||
_objectMap = new uint32[_objectMapCount];
|
||||
stream.seek(objectMapOffs);
|
||||
for (uint i = 0; i < _objectMapCount; ++i) {
|
||||
_objectMap[i] = stream.readUint32LE();
|
||||
stream.skip(4);
|
||||
}
|
||||
}
|
||||
|
||||
if (resource->_gameId == kGameIdDuckman)
|
||||
fixupProgInfosDuckman();
|
||||
|
||||
}
|
||||
|
||||
|
@ -274,4 +330,13 @@ ProgInfo *ScriptResource::getProgInfo(uint32 index) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32 ScriptResource::getObjectActorTypeId(uint32 objectId) {
|
||||
return _objectMap[(objectId & 0xFFFF) - 1];
|
||||
}
|
||||
|
||||
void ScriptResource::fixupProgInfosDuckman() {
|
||||
for (uint i = 0; i < _progInfosCount; ++i)
|
||||
_progInfos[i].fixupProgInfosDuckman();
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
|
|
@ -79,6 +79,7 @@ public:
|
|||
~TriggerObject();
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
bool findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &codeOffs);
|
||||
void fixupProgInfosDuckman();
|
||||
public:
|
||||
uint32 _objectId;
|
||||
uint _causesCount;
|
||||
|
@ -91,12 +92,16 @@ public:
|
|||
~ProgInfo();
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
bool findTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs);
|
||||
void getResources(uint &resourcesCount, uint32 *&resources);
|
||||
void fixupProgInfosDuckman();
|
||||
protected:
|
||||
uint16 _id;
|
||||
uint16 _unk;
|
||||
byte *_name;
|
||||
uint _triggerObjectsCount;
|
||||
TriggerObject *_triggerObjects;
|
||||
uint _resourcesCount;
|
||||
uint32 *_resources;
|
||||
TriggerObject *findTriggerObject(uint32 objectId);
|
||||
};
|
||||
|
||||
|
@ -104,10 +109,11 @@ class ScriptResource {
|
|||
public:
|
||||
ScriptResource();
|
||||
~ScriptResource();
|
||||
void load(byte *data, uint32 dataSize);
|
||||
void load(Resource *resource);
|
||||
byte *getThreadCode(uint32 threadId);
|
||||
byte *getCode(uint32 codeOffs);
|
||||
ProgInfo *getProgInfo(uint32 index);
|
||||
uint32 getObjectActorTypeId(uint32 objectId);
|
||||
public:
|
||||
byte *_data;
|
||||
uint32 _dataSize;
|
||||
|
@ -117,6 +123,11 @@ public:
|
|||
uint32 *_codeOffsets;
|
||||
uint _progInfosCount;
|
||||
ProgInfo *_progInfos;
|
||||
// Duckman specific
|
||||
uint32 _soundIds[27];
|
||||
uint _objectMapCount;
|
||||
uint32 *_objectMap;
|
||||
void fixupProgInfosDuckman();
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
|
|
@ -42,11 +42,7 @@ int ScriptThread::onUpdate() {
|
|||
opCall._result = kTSRun;
|
||||
opCall._callerThreadId = _threadId;
|
||||
while (!_terminated && opCall._result == kTSRun) {
|
||||
opCall._op = _scriptCodeIp[0];
|
||||
opCall._opSize = _scriptCodeIp[1] >> 1;
|
||||
opCall._threadId = _scriptCodeIp[1] & 1 ? _threadId : 0;
|
||||
opCall._code = _scriptCodeIp + 2;
|
||||
opCall._deltaOfs = opCall._opSize;
|
||||
loadOpcode(opCall);
|
||||
execOpcode(opCall);
|
||||
_scriptCodeIp += opCall._deltaOfs;
|
||||
}
|
||||
|
@ -55,6 +51,25 @@ int ScriptThread::onUpdate() {
|
|||
return opCall._result;
|
||||
}
|
||||
|
||||
void ScriptThread::loadOpcode(OpCall &opCall) {
|
||||
#if 0
|
||||
for (uint i = 0; i < 16; ++i)
|
||||
debugN("%02X ", _scriptCodeIp[i]);
|
||||
debug(".");
|
||||
#endif
|
||||
if (_vm->getGameId() == kGameIdDuckman) {
|
||||
opCall._op = _scriptCodeIp[0] & 0x7F;
|
||||
opCall._opSize = _scriptCodeIp[1];
|
||||
opCall._threadId = _scriptCodeIp[0] & 0x80 ? _threadId : 0;
|
||||
} else {
|
||||
opCall._op = _scriptCodeIp[0];
|
||||
opCall._opSize = _scriptCodeIp[1] >> 1;
|
||||
opCall._threadId = _scriptCodeIp[1] & 1 ? _threadId : 0;
|
||||
}
|
||||
opCall._code = _scriptCodeIp + 2;
|
||||
opCall._deltaOfs = opCall._opSize;
|
||||
}
|
||||
|
||||
void ScriptThread::execOpcode(OpCall &opCall) {
|
||||
_vm->_scriptOpcodes->execOpcode(this, opCall);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ public:
|
|||
uint32 _value8;
|
||||
uint32 _valueC;
|
||||
uint32 _value10;
|
||||
void loadOpcode(OpCall &opCall);
|
||||
void execOpcode(OpCall &opCall);
|
||||
};
|
||||
|
||||
|
|
|
@ -74,11 +74,13 @@ void SequenceOpcodes::initOpcodes() {
|
|||
OPCODE(17, opDisappearActor);
|
||||
OPCODE(18, opAppearForeignActor);
|
||||
OPCODE(19, opDisappearForeignActor);
|
||||
OPCODE(21, opMoveDelta);
|
||||
OPCODE(28, opNotifyThreadId1);
|
||||
OPCODE(29, opSetPathCtrY);
|
||||
OPCODE(33, opSetPathWalkPoints);
|
||||
OPCODE(35, opSetScale);
|
||||
OPCODE(36, opSetScaleLayer);
|
||||
OPCODE(37, opDeactivatePathWalkRects);
|
||||
OPCODE(38, opSetPathWalkRects);
|
||||
OPCODE(39, opSetPriority);
|
||||
OPCODE(40, opSetPriorityLayer);
|
||||
|
@ -243,6 +245,14 @@ void SequenceOpcodes::opDisappearForeignActor(Control *control, OpCall &opCall)
|
|||
foreignControl->disappearActor();
|
||||
}
|
||||
|
||||
void SequenceOpcodes::opMoveDelta(Control *control, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(deltaX);
|
||||
ARG_INT16(deltaY);
|
||||
control->_actor->_position.x += deltaX;
|
||||
control->_actor->_position.y += deltaY;
|
||||
}
|
||||
|
||||
void SequenceOpcodes::opNotifyThreadId1(Control *control, OpCall &opCall) {
|
||||
_vm->notifyThreadId(control->_actor->_notifyThreadId1);
|
||||
}
|
||||
|
@ -274,10 +284,14 @@ void SequenceOpcodes::opSetScaleLayer(Control *control, OpCall &opCall) {
|
|||
control->setActorScale(scale);
|
||||
}
|
||||
|
||||
void SequenceOpcodes::opDeactivatePathWalkRects(Control *control, OpCall &opCall) {
|
||||
control->_actor->_flags &= ~0x0010;
|
||||
}
|
||||
|
||||
void SequenceOpcodes::opSetPathWalkRects(Control *control, OpCall &opCall) {
|
||||
ARG_INT16(pathWalkRectsIndex);
|
||||
BackgroundResource *bgRes = _vm->_backgroundItems->getActiveBgResource();
|
||||
control->_actor->_flags |= 0x10;
|
||||
control->_actor->_flags |= 0x0010;
|
||||
// TODO control->_actor->_pathWalkRects = bgRes->getPathWalkRects(pathWalkRectsIndex - 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,11 +63,13 @@ protected:
|
|||
void opDisappearActor(Control *control, OpCall &opCall);
|
||||
void opAppearForeignActor(Control *control, OpCall &opCall);
|
||||
void opDisappearForeignActor(Control *control, OpCall &opCall);
|
||||
void opMoveDelta(Control *control, OpCall &opCall);
|
||||
void opNotifyThreadId1(Control *control, OpCall &opCall);
|
||||
void opSetPathCtrY(Control *control, OpCall &opCall);
|
||||
void opSetPathWalkPoints(Control *control, OpCall &opCall);
|
||||
void opSetScale(Control *control, OpCall &opCall);
|
||||
void opSetScaleLayer(Control *control, OpCall &opCall);
|
||||
void opDeactivatePathWalkRects(Control *control, OpCall &opCall);
|
||||
void opSetPathWalkRects(Control *control, OpCall &opCall);
|
||||
void opSetPriority(Control *control, OpCall &opCall);
|
||||
void opSetPriorityLayer(Control *control, OpCall &opCall);
|
||||
|
|
|
@ -110,11 +110,12 @@ int TalkThread::onUpdate() {
|
|||
_entryText = talkEntry->_text;
|
||||
_entryTblPtr = talkEntry->_tblPtr;
|
||||
if (_sequenceId1) {
|
||||
_pauseCtr = 0;
|
||||
// TODO _field30 = v6;
|
||||
_pauseCtr = 0;
|
||||
} else {
|
||||
_flags = 3;
|
||||
// TODO _field30 = 0;
|
||||
_flags |= 2;
|
||||
_flags |= 1;
|
||||
}
|
||||
if (_vm->isSoundActive()) {
|
||||
if (!_vm->cueVoice(talkEntry->_voiceName) && !_durationMult)
|
||||
|
@ -150,7 +151,7 @@ int TalkThread::onUpdate() {
|
|||
}
|
||||
_vm->startVoice(255, panX);
|
||||
}
|
||||
_vm->_input->discardButtons(16);
|
||||
_vm->_input->discardButtons(0x10);
|
||||
_status = 6;
|
||||
return kTSYield;
|
||||
|
||||
|
@ -161,7 +162,7 @@ int TalkThread::onUpdate() {
|
|||
// TODO _vm->removeText();
|
||||
if (_entryText && *_entryText) {
|
||||
refreshText();
|
||||
_vm->_input->discardButtons(16);
|
||||
_vm->_input->discardButtons(0x10);
|
||||
} else {
|
||||
_flags |= 8;
|
||||
}
|
||||
|
|
311
engines/illusions/talkthread_duckman.cpp
Normal file
311
engines/illusions/talkthread_duckman.cpp
Normal file
|
@ -0,0 +1,311 @@
|
|||
/* 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 "illusions/illusions_duckman.h"
|
||||
#include "illusions/talkthread_duckman.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/scriptman.h"
|
||||
#include "illusions/talkresource.h"
|
||||
#include "illusions/time.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// TalkThread_Duckman
|
||||
|
||||
TalkThread_Duckman::TalkThread_Duckman(IllusionsEngine_Duckman *vm, uint32 threadId, uint32 callingThreadId, uint notifyFlags,
|
||||
uint32 objectId, uint32 talkId, uint32 sequenceId1, uint32 sequenceId2)
|
||||
: Thread(vm, threadId, callingThreadId, notifyFlags), _vm(vm), _objectId(objectId), _talkId(talkId) {
|
||||
_type = kTTTalkThread;
|
||||
|
||||
if ((sequenceId1 & 0xFFFF0000) == 0x60000) {
|
||||
_sequenceId1 = sequenceId1;
|
||||
_sequenceId2 = sequenceId2;
|
||||
_namedPointId1 = 0;
|
||||
_namedPointId2 = 0;
|
||||
} else {
|
||||
_sequenceId1 = 0;
|
||||
_sequenceId2 = 0;
|
||||
_namedPointId1 = sequenceId1;
|
||||
_namedPointId2 = sequenceId2;
|
||||
}
|
||||
|
||||
if (_vm->checkActiveTalkThreads())
|
||||
_status = 1;
|
||||
else
|
||||
_status = 2;
|
||||
|
||||
_durationMult = _vm->clipTextDuration(_vm->_fieldE);
|
||||
_textDuration = _durationMult;
|
||||
_defDurationMult = _vm->clipTextDuration(240);
|
||||
|
||||
_tag = _vm->getCurrentScene();
|
||||
|
||||
}
|
||||
|
||||
int TalkThread_Duckman::onUpdate() {
|
||||
|
||||
TalkEntry *talkEntry;
|
||||
|
||||
switch (_status) {
|
||||
|
||||
case 1:
|
||||
if (_vm->checkActiveTalkThreads())
|
||||
return kTSYield;
|
||||
_status = 3;
|
||||
// Fallthrough to status 2
|
||||
|
||||
case 2:
|
||||
talkEntry = getTalkResourceEntry(_talkId);
|
||||
_flags = 0;
|
||||
_entryText = talkEntry->_text;
|
||||
_currEntryText = 0;
|
||||
_entryTblPtr = talkEntry->_tblPtr;
|
||||
_flags = 0;
|
||||
if (_sequenceId1) {
|
||||
_pauseCtr = 0;
|
||||
_pauseCtrPtr = &_pauseCtr;
|
||||
} else {
|
||||
_pauseCtrPtr = 0;
|
||||
_flags |= 2;
|
||||
_flags |= 1;
|
||||
}
|
||||
if (_vm->isSoundActive()) {
|
||||
if (!_vm->cueVoice(talkEntry->_voiceName) && !_durationMult)
|
||||
_durationMult = _defDurationMult;
|
||||
} else {
|
||||
_flags |= 4;
|
||||
if (!_durationMult)
|
||||
_durationMult = _defDurationMult;
|
||||
}
|
||||
if (_objectId == 0 || _durationMult == 0)
|
||||
_flags |= 8;
|
||||
_status = 3;
|
||||
// Fallthrough to status 3
|
||||
|
||||
case 3:
|
||||
if (!(_flags & 4) && !_vm->isVoiceCued())
|
||||
return kTSYield;
|
||||
_status = 4;
|
||||
// Fallthrough to status 4
|
||||
|
||||
case 4:
|
||||
if (!(_flags & 8) ) {
|
||||
uint32 actorTypeId = _vm->getObjectActorTypeId(_objectId);
|
||||
// TODO getActorTypeColor(actorTypeId, &_colorR, &_colorG, &_colorB);
|
||||
refreshText();
|
||||
}
|
||||
if (!(_flags & 2)) {
|
||||
Control *control = _vm->_dict->getObjectControl(_objectId);
|
||||
control->startTalkActor(_sequenceId1, _entryTblPtr, _threadId);
|
||||
}
|
||||
if (!(_flags & 4)) {
|
||||
int16 panX = 0;
|
||||
if (_flags & 1) {
|
||||
if (_namedPointId2) {
|
||||
panX = _vm->getNamedPointPosition(_namedPointId2).x;
|
||||
panX = _vm->convertPanXCoord(panX);
|
||||
}
|
||||
} else {
|
||||
Control *control = _vm->_dict->getObjectControl(_objectId);
|
||||
panX = control->getActorPosition().x;
|
||||
panX = _vm->convertPanXCoord(panX);
|
||||
}
|
||||
_vm->startVoice(255, panX);
|
||||
}
|
||||
_vm->_input->discardButtons(0x20);
|
||||
_status = 5;
|
||||
return kTSYield;
|
||||
|
||||
case 5:
|
||||
if (!(_flags & 4) && !_vm->isVoicePlaying())
|
||||
_flags |= 4;
|
||||
if (!(_flags & 8) && isTimerExpired(_textStartTime, _textEndTime)) {
|
||||
// TODO _vm->removeText();
|
||||
if (_entryText && *_entryText) {
|
||||
refreshText();
|
||||
_vm->_input->discardButtons(0x20);
|
||||
} else {
|
||||
_flags |= 8;
|
||||
}
|
||||
}
|
||||
if (!(_flags & 2)) {
|
||||
if (*_pauseCtrPtr < 0) {
|
||||
++(*_pauseCtrPtr);
|
||||
Control *control = _vm->_dict->getObjectControl(_objectId);
|
||||
control->startSequenceActor(_sequenceId2, 2, 0);
|
||||
_flags |= 2;
|
||||
}
|
||||
}
|
||||
if (_objectId && _vm->_input->pollButton(0x20)) {
|
||||
if (!(_flags & 8)) {
|
||||
// TODO largeObj_removeText();
|
||||
if (_entryText && *_entryText)
|
||||
refreshText();
|
||||
else
|
||||
_flags |= 8;
|
||||
}
|
||||
if (_flags & 8) {
|
||||
if (!(_flags & 4)) {
|
||||
_vm->stopVoice();
|
||||
_flags |= 4;
|
||||
}
|
||||
if (!(_flags & 2)) {
|
||||
Control *control = _vm->_dict->getObjectControl(_objectId);
|
||||
control->clearNotifyThreadId1();
|
||||
control->startSequenceActor(_sequenceId2, 2, 0);
|
||||
_flags |= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
debug("8: %d", (_flags & 8) != 0);
|
||||
debug("4: %d", (_flags & 4) != 0);
|
||||
debug("2: %d", (_flags & 2) != 0);
|
||||
*/
|
||||
if ((_flags & 8) && (_flags & 2) && (_flags & 4)) {
|
||||
debug("TALK DONE");
|
||||
_vm->_input->discardButtons(0x20);
|
||||
return kTSTerminate;
|
||||
}
|
||||
return kTSYield;
|
||||
|
||||
case 6:
|
||||
if (!(_flags & 2)) {
|
||||
Control *control = _vm->_dict->getObjectControl(_objectId);
|
||||
if (*_pauseCtrPtr >= 0) {
|
||||
control->clearNotifyThreadId1();
|
||||
} else {
|
||||
++(*_pauseCtrPtr);
|
||||
}
|
||||
control->startSequenceActor(_sequenceId2, 2, 0);
|
||||
_flags |= 2;
|
||||
}
|
||||
return kTSTerminate;
|
||||
|
||||
}
|
||||
|
||||
return kTSTerminate;
|
||||
|
||||
}
|
||||
|
||||
void TalkThread_Duckman::onSuspend() {
|
||||
}
|
||||
|
||||
void TalkThread_Duckman::onNotify() {
|
||||
}
|
||||
|
||||
void TalkThread_Duckman::onPause() {
|
||||
}
|
||||
|
||||
void TalkThread_Duckman::onResume() {
|
||||
}
|
||||
|
||||
void TalkThread_Duckman::onTerminated() {
|
||||
if (_status == 5) {
|
||||
if (!(_flags & 4))
|
||||
_vm->stopVoice();
|
||||
if (!(_flags & 8)) {
|
||||
// TODO largeObj_removeText();
|
||||
}
|
||||
if (!(_flags & 2)) {
|
||||
Control *control = _vm->_dict->getObjectControl(_objectId);
|
||||
if (control) {
|
||||
control->clearNotifyThreadId1();
|
||||
control->startSequenceActor(_sequenceId2, 2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TalkThread_Duckman::onKill() {
|
||||
_callingThreadId = 0;
|
||||
sendMessage(kMsgClearSequenceId1, 0);
|
||||
sendMessage(kMsgClearSequenceId2, 0);
|
||||
}
|
||||
|
||||
uint32 TalkThread_Duckman::sendMessage(int msgNum, uint32 msgValue) {
|
||||
// TODO
|
||||
switch (msgNum) {
|
||||
case kMsgQueryTalkThreadActive:
|
||||
if (_status != 1 && _status != 2)
|
||||
return 1;
|
||||
break;
|
||||
case kMsgClearSequenceId1:
|
||||
_sequenceId1 = 0;
|
||||
_flags |= 3;
|
||||
// TODO _pauseCtrPtr = 0;
|
||||
break;
|
||||
case kMsgClearSequenceId2:
|
||||
_sequenceId2 = 0;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TalkThread_Duckman::refreshText() {
|
||||
_currEntryText = _entryText;
|
||||
int charCount = insertText();
|
||||
uint32 duration = _durationMult;
|
||||
if (charCount < 80) {
|
||||
duration = _durationMult * charCount / 80;
|
||||
if (duration < 25 * _durationMult / 100)
|
||||
duration = 25 * _durationMult / 100;
|
||||
if (duration < 60)
|
||||
duration = 60;
|
||||
}
|
||||
_textDuration = duration;
|
||||
_textStartTime = getCurrentTime();
|
||||
_textEndTime = _textStartTime + _textDuration;
|
||||
}
|
||||
|
||||
static char *debugW2I(byte *wstr) {
|
||||
static char buf[65];
|
||||
char *p = buf;
|
||||
while (*wstr != 0) {
|
||||
*p++ = *wstr;
|
||||
wstr += 2;
|
||||
}
|
||||
*p = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
int TalkThread_Duckman::insertText() {
|
||||
int charCount = 100;
|
||||
debug("%08X %08X [%s]", _threadId, _talkId, debugW2I(_currEntryText));
|
||||
_entryText = 0;
|
||||
// TODO _vm->getDimensions1(&dimensions);
|
||||
// TODO _vm->insertText(_currEntryText, 0x00120001, dimensions, 0, 2, 0, 0, _colorR, _colorG, _colorB, 0, &outTextPtr);
|
||||
// TODO _vm->charCount = (char *)outTextPtr - (char *)text;
|
||||
// TODO _entryText = outTextPtr;
|
||||
// TODO _vm->getPoint1(&pt);
|
||||
// TODO _vm->updateTextInfoPosition(pt);
|
||||
return charCount >> 1;
|
||||
}
|
||||
|
||||
TalkEntry *TalkThread_Duckman::getTalkResourceEntry(uint32 talkId) {
|
||||
TalkEntry *talkEntry = _vm->_dict->findTalkEntry(talkId);
|
||||
return talkEntry;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
86
engines/illusions/talkthread_duckman.h
Normal file
86
engines/illusions/talkthread_duckman.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_TALKTHREAD_DUCKMAN_H
|
||||
#define ILLUSIONS_TALKTHREAD_DUCKMAN_H
|
||||
|
||||
#include "illusions/thread.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_Duckman;
|
||||
struct TalkEntry;
|
||||
|
||||
enum {
|
||||
kMsgQueryTalkThreadActive = 0,
|
||||
kMsgClearSequenceId1 = 1,
|
||||
kMsgClearSequenceId2 = 2
|
||||
};
|
||||
|
||||
class TalkThread_Duckman : public Thread {
|
||||
public:
|
||||
TalkThread_Duckman(IllusionsEngine_Duckman *vm, uint32 threadId, uint32 callingThreadId, uint notifyFlags,
|
||||
uint32 objectId, uint32 talkId, uint32 sequenceId1, uint32 sequenceId2);
|
||||
virtual int onUpdate();
|
||||
virtual void onSuspend();
|
||||
virtual void onNotify();
|
||||
virtual void onPause();
|
||||
virtual void onResume();
|
||||
virtual void onTerminated();
|
||||
virtual void onKill();
|
||||
virtual uint32 sendMessage(int msgNum, uint32 msgValue);
|
||||
public:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
//field0 dw
|
||||
int _status;
|
||||
uint _flags;
|
||||
uint32 _textStartTime;
|
||||
uint32 _textEndTime;
|
||||
uint32 _textDuration;
|
||||
uint32 _defDurationMult;
|
||||
uint32 _textDurationElapsed;
|
||||
uint32 _durationMult;
|
||||
//field12 dw
|
||||
uint32 _objectId;
|
||||
uint32 _talkId;
|
||||
uint32 _sequenceId1;
|
||||
uint32 _sequenceId2;
|
||||
uint32 _namedPointId1;
|
||||
uint32 _namedPointId2;
|
||||
byte *_entryTblPtr;
|
||||
byte *_entryText;
|
||||
byte *_currEntryText;
|
||||
//field30 dd
|
||||
uint32 _voiceStartTime;
|
||||
uint32 _voiceEndTime;
|
||||
uint32 _voiceDuration;
|
||||
uint32 _voiceDurationElapsed;
|
||||
int *_pauseCtrPtr;
|
||||
byte _colorR, _colorG, _colorB;
|
||||
void refreshText();
|
||||
int insertText();
|
||||
TalkEntry *getTalkResourceEntry(uint32 talkId);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_TALKTHREAD_H
|
|
@ -197,6 +197,14 @@ void ThreadList::terminateThreads(uint32 threadId) {
|
|||
}
|
||||
}
|
||||
|
||||
void ThreadList::terminateActiveThreads(uint32 threadId) {
|
||||
for (Iterator it = _threads.begin(); it != _threads.end(); ++it) {
|
||||
Thread *thread = *it;
|
||||
if (thread->_pauseCtr <= 0 && thread->_threadId != threadId)
|
||||
thread->terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadList::terminateThreadsByTag(uint32 tag, uint32 threadId) {
|
||||
for (Iterator it = _threads.begin(); it != _threads.end(); ++it) {
|
||||
Thread *thread = *it;
|
||||
|
@ -213,6 +221,14 @@ void ThreadList::suspendThreadsByTag(uint32 tag, uint32 threadId) {
|
|||
}
|
||||
}
|
||||
|
||||
void ThreadList::notifyThreads(uint32 threadId) {
|
||||
for (Iterator it = _threads.begin(); it != _threads.end(); ++it) {
|
||||
Thread *thread = *it;
|
||||
if (thread->_threadId != threadId)
|
||||
thread->notify();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadList::notifyThreadsByTag(uint32 tag, uint32 threadId) {
|
||||
for (Iterator it = _threads.begin(); it != _threads.end(); ++it) {
|
||||
Thread *thread = *it;
|
||||
|
@ -229,6 +245,14 @@ void ThreadList::pauseThreads(uint32 threadId) {
|
|||
}
|
||||
}
|
||||
|
||||
void ThreadList::suspendThreads(uint32 threadId) {
|
||||
for (Iterator it = _threads.begin(); it != _threads.end(); ++it) {
|
||||
Thread *thread = *it;
|
||||
if (thread->_threadId != threadId)
|
||||
thread->suspend();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadList::resumeThreads(uint32 threadId) {
|
||||
for (Iterator it = _threads.begin(); it != _threads.end(); ++it) {
|
||||
Thread *thread = *it;
|
||||
|
|
|
@ -86,10 +86,13 @@ public:
|
|||
void notifyTimerThreads(uint32 callingThreadId);
|
||||
void suspendTimerThreads(uint32 callingThreadId);
|
||||
void terminateThreads(uint32 threadId);
|
||||
void terminateActiveThreads(uint32 threadId);
|
||||
void terminateThreadsByTag(uint32 tag, uint32 threadId);
|
||||
void suspendThreadsByTag(uint32 tag, uint32 threadId);
|
||||
void notifyThreads(uint32 threadId);
|
||||
void notifyThreadsByTag(uint32 tag, uint32 threadId);
|
||||
void pauseThreads(uint32 threadId);
|
||||
void suspendThreads(uint32 threadId);
|
||||
void resumeThreads(uint32 threadId);
|
||||
void endTalkThreads();
|
||||
void endTalkThreadsNoNotify();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue