imported teenagent engine sources.

svn-id: r43922
This commit is contained in:
Vladimir Menshakov 2009-09-03 20:59:17 +00:00
parent 9b2104db32
commit ebe1b94eb1
32 changed files with 5348 additions and 0 deletions

View File

@ -157,6 +157,9 @@ public:
#if PLUGIN_ENABLED_STATIC(TUCKER)
LINK_PLUGIN(TUCKER)
#endif
#if PLUGIN_ENABLED_STATIC(TEENAGENT)
LINK_PLUGIN(TEENAGENT)
#endif
// Music plugins
// TODO: Use defines to disable or enable each MIDI driver as a

1
configure vendored
View File

@ -105,6 +105,7 @@ add_engine sword2 "Broken Sword 2" yes
add_engine tinsel "Tinsel" yes
add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes
add_engine tucker "Bud Tucker in Double Trouble" yes
add_engine teenagent "Teen Agent" no
#

View File

@ -145,3 +145,8 @@ ifdef ENABLE_TUCKER
DEFINES += -DENABLE_TUCKER=$(ENABLE_TUCKER)
MODULES += engines/tucker
endif
ifdef ENABLE_TEENAGENT
DEFINES += -DENABLE_TEENAGENT=$(ENABLE_TEENAGENT)
MODULES += engines/teenagent
endif

View File

@ -0,0 +1,70 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/actor.cpp $
* $Id: objects.h 172 2009-08-11 08:06:58Z megath $
*/
#include "actor.h"
#include "objects.h"
using namespace TeenAgent;
void Actor::render(Graphics::Surface * surface, const Common::Point & position, uint8 orientation, int delta_frame) {
uint8 frames_left_right[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
uint8 frames_up[] = {18, 19, 20, 21, 22, 23, 24, 25, };
uint8 frames_down[] = {10, 11, 12, 13, 14, 15, 16, 17, };
Surface * s = NULL;
if (delta_frame == 0) {
index = 0; //static animation
}
int dx, dy;
switch(orientation) {
case Object::ActorLeft:
case Object::ActorRight:
if (index >= sizeof(frames_left_right))
index = 1;
s = frames + frames_left_right[index];
dx = 11;
dy = 62;
break;
case Object::ActorUp:
if (index >= sizeof(frames_up))
index = 1;
s = frames + frames_up[index];
dx = 29;
dy = 67;
break;
case Object::ActorDown:
if (index >= sizeof(frames_down))
index = 1;
s = frames + frames_down[index];
dx = 29;
dy = 67;
break;
default:
return;
}
index += delta_frame;
if (s != NULL)
s->render(surface, position.x - dx, position.y - dy, orientation == Object::ActorLeft);
}

34
engines/teenagent/actor.h Normal file
View File

@ -0,0 +1,34 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/objects.h $
* $Id: objects.h 172 2009-08-11 08:06:58Z megath $
*/
#include "animation.h"
#include "common/rect.h"
namespace TeenAgent {
class Actor : public Animation {
public:
void render(Graphics::Surface * surface, const Common::Point & position, uint8 orientation, int delta_frame);
};
}

View File

@ -0,0 +1,185 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/animation.cpp $
* $Id: animation.cpp 296 2009-09-01 19:55:58Z megath $
*/
#include "animation.h"
#include "common/endian.h"
using namespace TeenAgent;
Animation::Animation() : id(0), x(0), y(0), loop(true), data(0), data_size(0), frames_count(0), frames(0), index(0) {
}
Surface * Animation::currentFrame(int dt) {
if (frames == NULL || frames_count == 0)
return NULL;
Surface * r;
if (data != NULL) {
uint32 frame = 3 * index;
//debug(0, "%u/%u", index, data_size / 3);
index += dt;
if (!loop && index >= data_size / 3) {
return NULL;
}
if (data[frame] - 1 >= frames_count) {
warning("invalid frame %u(0x%x) (max %u) index %u, mod %u", frame, frame, frames_count, index - 1, data_size / 3);
return NULL;
}
r = frames + data[frame] - 1;
uint16 pos = READ_LE_UINT16(data + frame + 1);
index %= (data_size / 3);
if (pos != 0) {
x = r->x = pos % 320;
y = r->y = pos / 320;
}
} else {
//debug(0, "index %u", index);
r = frames + index;
index += dt;
index %= frames_count;
}
return r;
}
void Animation::free() {
id = 0;
x = y = 0;
loop = true;
delete[] data;
data = NULL;
data_size = 0;
frames_count = 0;
delete[] frames;
frames = NULL;
index = 0;
}
void Animation::load(Common::SeekableReadStream * s, Type type) {
//fixme: do not reload the same animation each time
free();
if (s == NULL && s->size() <= 1) {
debug(0, "empty animation");
return;
}
uint16 pos = 0;
int off = 0;
switch(type) {
case TypeLan:
data_size = s->readUint16LE();
if (s->eos()) {
debug(0, "empty animation");
return;
}
data_size -= 2;
data = new byte[data_size];
data_size = s->read(data, data_size);
/* for(int i = 0; i < data_size; ++i) {
debug(0, "%02x ", data[i]);
}
debug(0, ", %u frames", data_size / 3);
*/
frames_count = s->readByte();
debug(0, "%u physical frames", frames_count);
if (frames_count == 0)
return;
frames = new Surface[frames_count];
s->skip(frames_count * 2 - 2); //sizes
pos = s->readUint16LE();
//debug(0, "pos?: %04x", pos);
for(uint16 i = 0; i < frames_count; ++i) {
frames[i].load(s, Surface::TypeLan);
frames[i].x = 0;
frames[i].y = 0;
}
break;
case TypeInventory: {
data_size = 3 * s->readByte();
data = new byte[data_size];
frames_count = 0;
for(byte i = 0; i < data_size / 3; ++i) {
int idx = i * 3;
byte unk = s->readByte();
data[idx] = s->readByte();
if (data[idx] == 0)
data[idx] = 1; //fixme: investigate
if (data[idx] > frames_count)
frames_count = data[idx];
data[idx + 1] = 0;
data[idx + 2] = 0;
//debug(0, "frame #%u", data[idx]);
}
frames = new Surface[frames_count];
for(uint16 i = 0; i < frames_count; ++i) {
frames[i].load(s, Surface::TypeOns);
}
}
break;
case TypeVaria:
frames_count = s->readByte();
debug(0, "loading varia resource, %u physical frames", frames_count);
uint16 offset[255];
for(byte i = 0; i < frames_count; ++i) {
offset[i] = s->readUint16LE();
debug(0, "%u: %04x", i, offset[i]);
}
frames = new Surface[frames_count];
for(uint16 i = 0; i < frames_count; ++i) {
debug(0, "%04x", offset[i]);
s->seek(offset[i] + off);
frames[i].load(s, Surface::TypeOns);
frames[i].x = 0;
frames[i].y = 0;
}
break;
}
debug(0, "%u frames", data_size / 3);
}
Animation::~Animation() {
free();
}

View File

@ -0,0 +1,64 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/animation.h $
* $Id: animation.h 214 2009-08-14 06:09:26Z megath $
*/
#ifndef TEENAGENT_ANIMATION_H__
#define TEENAGENT_ANIMATION_H__
#include "common/stream.h"
#include "surface.h"
namespace TeenAgent {
class Animation {
public:
uint16 id, x, y;
bool loop;
enum Type {TypeLan, TypeVaria, TypeInventory};
Animation();
void load(Common::SeekableReadStream * s, Type type = TypeLan);
void free();
Surface * currentFrame(int dt = 1);
~Animation();
bool empty() const { return frames == NULL; }
//uint16 width() const { return frames? frames[0].w: 0; }
//uint16 height() const { return frames? frames[0].h: 0; }
protected:
byte * data;
uint16 data_size;
uint16 frames_count;
Surface * frames;
uint16 index;
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/detection.cpp $
* $Id: detection.cpp 215 2009-08-14 07:11:27Z megath $
*/
#include "engines/advancedDetector.h"
#include "base/plugins.h"
#include "teenagent/teenagent.h"
#include "common/system.h"
#include "common/savefile.h"
static const PlainGameDescriptor teenAgentGames[] = {
{ "teenagent", "Teen agent" },
{ 0, 0 }
};
static const ADGameDescription teenAgentGameDescriptions[] = {
{
"teenagent",
"",
AD_ENTRY1s("teenagnt.exe", "b886cae8f875ea5eaefed04a8cc3c8a1", 152690),
Common::EN_ANY,
Common::kPlatformPC,
ADGF_NO_FLAGS,
Common::GUIO_NONE
},
AD_TABLE_END_MARKER
};
static const ADParams detectionParams = {
(const byte *)teenAgentGameDescriptions,
sizeof(ADGameDescription),
512,
teenAgentGames,
0,
"teenagent",
0,
0,
Common::GUIO_NONE
};
#define MAX_SAVES 20
class TeenAgentMetaEngine : public AdvancedMetaEngine {
public:
TeenAgentMetaEngine() : AdvancedMetaEngine(detectionParams) {
}
virtual const char *getName() const {
return "Teen Agent Engine";
}
virtual const char *getOriginalCopyright() const {
return "TEENAGENT demo and TEENAGENT name copyright (c) Metropolis 1994.";
}
virtual bool hasFeature(MetaEngineFeature f) const {
switch (f) {
case kSupportsListSaves:
case kSupportsDeleteSave:
case kSupportsLoadingDuringStartup:
//case kSavesSupportThumbnail:
return true;
default:
return false;
}
}
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
if (desc) {
*engine = new TeenAgent::TeenAgentEngine(syst);
}
return desc != 0;
}
// virtual const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const {
// return 0;
// }
static Common::String generateGameStateFileName(const char *target, int slot) {
char slotStr[16];
snprintf(slotStr, sizeof(slotStr), ".%d", slot);
return slotStr;
}
virtual SaveStateList listSaves(const char *target) const {
Common::String pattern = target;
pattern += ".*";
Common::StringList filenames = g_system->getSavefileManager()->listSavefiles(pattern);
bool slotsTable[MAX_SAVES];
memset(slotsTable, 0, sizeof(slotsTable));
SaveStateList saveList;
for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
int slot;
const char *ext = strrchr(file->c_str(), '.');
if (ext && (slot = atoi(ext + 1)) >= 0 && slot < MAX_SAVES) {
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
if (in) {
slotsTable[slot] = true;
delete in;
}
}
}
for (int slot = 0; slot < MAX_SAVES; ++slot) {
if (slotsTable[slot]) {
char description[64];
snprintf(description, sizeof(description), "teenagent.%02d", slot);
saveList.push_back(SaveStateDescriptor(slot, description));
}
}
return saveList;
}
virtual int getMaximumSaveSlot() const {
return MAX_SAVES - 1;
}
virtual void removeSaveState(const char *target, int slot) const {
Common::String filename = generateGameStateFileName(target, slot);
g_system->getSavefileManager()->removeSavefile(filename);
}
};
#if PLUGIN_ENABLED_DYNAMIC(TEENAGENT)
REGISTER_PLUGIN_DYNAMIC(TEENAGENT, PLUGIN_TYPE_ENGINE, TeenAgentMetaEngine);
#else
REGISTER_PLUGIN_STATIC(TEENAGENT, PLUGIN_TYPE_ENGINE, TeenAgentMetaEngine);
#endif

View File

@ -0,0 +1,106 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/objects.h $
* $Id: objects.h 172 2009-08-11 08:06:58Z megath $
*/
#include "dialog.h"
#include "resources.h"
#include "scene.h"
using namespace TeenAgent;
void Dialog::show(Scene * scene, uint16 addr, uint16 animation) {
debug(0, "Dialog::show(%04x, %u)", addr, animation);
Resources * res = Resources::instance();
int n = 0;
Common::String message;
byte color = 0xd1;
while (n < 4) {
byte c = res->eseg.get_byte(addr++);
switch(c) {
case 0:
++n;
if (n == 3) {
color = color == 0xd1? 0xd0: 0xd1;
//debug(0, "changing color", message);
}
continue;
case 0xff:
{
SceneEvent e(SceneEvent::WaitForAnimation);
scene->push(e);
}
++n;
continue;
default:
if (n > 1) {
if (!message.empty()) {
if (animation != 0) {
SceneEvent e(SceneEvent::PlayAnimation);
e.animation = animation;
e.color = 0x83; //3rd slot, async animation
scene->push(e);
}
SceneEvent e(SceneEvent::Message);
e.message = message;
e.color = color;
scene->push(e);
}
message = (const char *)Resources::instance()->eseg.ptr(addr - 1);
} else if (n == 1) {
message += '\n';
message += (const char *)Resources::instance()->eseg.ptr(addr - 1);
} else if (n == 0 && message.empty()) {
message = (const char *)Resources::instance()->eseg.ptr(addr - 1);
}
n = 0;
}
}
if (!message.empty()) {
if (animation != 0) {
SceneEvent e(SceneEvent::PlayAnimation);
e.animation = animation;
e.color = 0x83; //3rd slot, async animation
scene->push(e);
} //copy paste ninja was here
SceneEvent e(SceneEvent::Message);
e.message = message;
e.color = color;
scene->push(e);
}
}
uint16 Dialog::pop(Scene *scene, uint16 addr, uint16 animation) {
debug(0, "Dialog::pop(%04x, %u)", addr, animation);
Resources * res = Resources::instance();
uint16 next;
do {
next = res->dseg.get_word(addr);
addr += 2;
} while(next == 0);
uint16 next2 = res->dseg.get_word(addr);
if (next2 != 0xffff)
res->dseg.set_word(addr - 2, 0);
show(scene, next, animation);
return next;
}

View File

@ -0,0 +1,42 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/objects.h $
* $Id: objects.h 172 2009-08-11 08:06:58Z megath $
*/
#ifndef TEENAGENT_DIALOG_H__
#define TEENAGENT_DIALOG_H__
#include "common/endian.h"
#include "common/str.h"
namespace TeenAgent {
class Scene;
class Dialog {
public:
static uint16 pop(Scene *scene, uint16 addr, uint16 animation = 0);
static void show(Scene *scene, uint16 addr, uint16 animation = 0);
};
}
#endif

142
engines/teenagent/font.cpp Normal file
View File

@ -0,0 +1,142 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/font.cpp $
* $Id: font.cpp 242 2009-08-15 11:44:27Z megath $
*/
#include "font.h"
#include "resources.h"
using namespace TeenAgent;
Font::Font() : grid_color(0xd0), color(0xd1), data(0) {
}
void Font::load(int id) {
delete[] data;
data = NULL;
Common::SeekableReadStream * s = Resources::instance()->varia.getStream(id);
if (s == NULL)
error("loading font %d failed", id);
data = new byte[s->size()];
s->read(data, s->size());
debug(0, "font size: %d", s->size());
}
uint Font::render(Graphics::Surface *surface, int x, int y, char c) {
unsigned idx = (unsigned char)c;
if (idx < 0x20 || idx >= 0x81) {
debug(0, "unhandled char 0x%02x", idx);
return 0;
}
idx -= 0x20;
byte * glyph = data + READ_LE_UINT16(data + idx * 2);
uint h = glyph[0], w = glyph[1];
if (surface == NULL || surface->pixels == NULL)
return w;
//debug(0, "char %c, width: %dx%d", c, w, h);
glyph += 2;
byte * dst = (byte *)surface->getBasePtr(x, y);
for(uint i = 0; i < h; ++i) {
for(uint j = 0; j < w; ++j) {
byte v = *glyph++;
switch(v) {
case 1:
dst[j] = 0;
break;
case 2:
dst[j] = color;
break;
}
}
dst += surface->pitch;
}
return w - 1;
}
static uint find_in_str(const Common::String &str, char c, uint pos = 0) {
while(pos < str.size() && str[pos] != c) ++pos;
return pos;
}
uint Font::render(Graphics::Surface *surface, int x, int y, const Common::String &str, bool show_grid) {
const int height = 10;
if (surface != NULL) {
uint max_w = render(NULL, 0, 0, str, false);
if (show_grid)
grid(surface, x - 4, y - 2, max_w + 8, 8 + 6, grid_color);
uint i = 0, j;
do {
j = find_in_str(str, '\n', i);
Common::String line(str.c_str() + i, j - i);
//debug(0, "line: %s", line.c_str());
uint w = render(NULL, 0, 0, line, false);
int xp = x + (max_w - w) / 2;
for (uint k = 0; k < line.size(); ++k) {
xp += render(surface, xp, y, line[k]);
}
y += height;
i = j + 1;
} while(i < str.size());
return max_w;
} else {
//surface == NULL;
uint w = 0, max_w = 0;
for (uint i = 0; i < str.size(); ++i) {
char c = str[i];
if (c == '\n') {
y += height;
if (w > max_w)
max_w = w;
w = 0;
continue;
}
w += render(NULL, 0, 0, c);
}
if (w > max_w)
max_w = w;
return max_w;
}
}
void Font::grid(Graphics::Surface *surface, int x, int y, int w, int h, byte color) {
byte * dst = (byte *)surface->getBasePtr(x, y);
for(int i = 0; i < h; ++i) {
for(int j = 0; j < w; ++j) {
if (((i ^ j) & 1) == 0)
dst[j] = color;
}
dst += surface->pitch;
}
}
Font::~Font() {
delete[] data;
}

48
engines/teenagent/font.h Normal file
View 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.
*
* $URL: https://www.switchlink.se/svn/teen/font.h $
* $Id: font.h 173 2009-08-11 08:10:22Z megath $
*/
#ifndef TEENAGENT_FONT_H__
#define TEENAGENT_FONT_H__
#include "graphics/surface.h"
namespace TeenAgent {
class Font {
public:
byte grid_color, color;
Font();
void load(int id);
uint render(Graphics::Surface *surface, int x, int y, const Common::String &str, bool grid = false);
uint render(Graphics::Surface *surface, int x, int y, char c);
static void grid(Graphics::Surface *surface, int x, int y, int w, int h, byte color);
~Font();
private:
byte *data;
};
}
#endif

View File

@ -0,0 +1,285 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/objects.h $
* $Id: objects.h 172 2009-08-11 08:06:58Z megath $
*/
#include "inventory.h"
#include "resources.h"
#include "common/stream.h"
#include "objects.h"
#include "teenagent.h"
using namespace TeenAgent;
void Inventory::init(TeenAgentEngine * engine) {
_engine = engine;
_active = false;
Resources * res = Resources::instance();
Common::SeekableReadStream * s = res->varia.getStream(3);
assert(s != NULL);
debug(0, "loading inventory background...");
background.load(s, Surface::TypeOns);
items = res->varia.getStream(4);
assert(items != NULL);
byte offsets = items->readByte();
assert(offsets == 92);
for(byte i = 0; i < offsets; ++i) {
offset[i] = items->readUint16LE();
}
objects = res->dseg.ptr(0xc4a4);
inventory = res->dseg.ptr(0xc48d);
for(int y = 0; y < 4; ++y)
for(int x = 0; x < 6; ++x) {
int i = y * 6 + x;
graphics[i].rect.left = 28 + 45 * x - 1;
graphics[i].rect.top = 23 + 31 * y - 1;
graphics[i].rect.right = graphics[i].rect.left + 40;
graphics[i].rect.bottom = graphics[i].rect.top + 26;
}
hovered_obj = selected_obj = NULL;
}
bool Inventory::has(byte item) const {
for(int i = 0; i < 24; ++i) {
if (inventory[i] == item)
return true;
}
return false;
}
void Inventory::remove(byte item) {
debug(0, "removing %02x from inventory", item);
int i;
for(i = 0; i < 24; ++i) {
if (inventory[i] == item) {
break;
}
}
for(; i < 23; ++i) {
inventory[i] = inventory[i + 1];
graphics[i].free();
}
inventory[23] = 0;
graphics[23].free();
}
void Inventory::clear() {
debug(0, "clearing inventory");
for(int i = 0; i < 24; ++i) {
inventory[i] = 0;
graphics[i].free();
}
}
void Inventory::add(byte item) {
if (has(item))
return;
debug(0, "adding %02x to inventory", item);
for(int i = 0; i < 24; ++i) {
if (inventory[i] == 0) {
inventory[i] = item;
return;
}
}
error("no room for item %02x", item);
}
bool Inventory::processEvent(const Common::Event &event) {
Resources * res = Resources::instance();
switch(event.type) {
case Common::EVENT_MOUSEMOVE:
mouse = event.mouse;
if (!active() && event.mouse.y < 5) {
activate(true);
return _active;
}
if (event.mouse.x < 17 || event.mouse.x >= 303 || event.mouse.y >= 153) {
activate(false);
return _active;
}
if (!_active)
return false;
hovered_obj = NULL;
for(int i = 0; i < 24; ++i) {
byte item = inventory[i];
if (item == 0)
continue;
graphics[i].hovered = graphics[i].rect.in(mouse);
if (graphics[i].hovered)
hovered_obj = (InventoryObject *)res->dseg.ptr(READ_LE_UINT16(objects + item * 2));
}
return true;
case Common::EVENT_LBUTTONDOWN: {
//check combine
if (selected_obj == NULL || hovered_obj == NULL)
return _active;
int id1 = selected_obj->id;
int id2 = hovered_obj->id;
debug(0, "combine(0x%02x, 0x%02x)!", id1, id2);
byte * table = res->dseg.ptr(0xC335);
while(table[0] != 0 && table[1] != 0) {
if (
(id1 == table[0] && id2 == table[1]) ||
(id2 == table[0] && id1 == table[1])
) {
remove(id1);
remove(id2);
add(table[2]);
uint16 msg = READ_LE_UINT16(table + 3);
_engine->displayMessage(msg);
_engine->playSoundNow(69);
activate(false);
resetSelectedObject();
return true;
}
table += 5;
}
_engine->displayMessage(0xc3e2);
activate(false);
resetSelectedObject();
return true;
}
case Common::EVENT_RBUTTONDOWN:
if (!_active)
return false;
if (hovered_obj != NULL) {
byte id = hovered_obj->id;
debug(0, "rclick object %u", id);
uint i = 0;
for(byte * table = res->dseg.ptr(0xBB6F + 3); //original offset + 3 bytes.
table[0] != 0 && i < 7; table += 3, ++i) {
if (table[0] == id) {
resetSelectedObject();
activate(false);
if (_engine->processCallback(READ_LE_UINT16(table + 1)))
return true;
else {
//some callbacks returns false if they need to display default description
_engine->displayMessage(hovered_obj->description());
activate(false);
resetSelectedObject();
return true;
}
}
}
}
selected_obj = hovered_obj;
if (selected_obj)
debug(0, "selected object %s", selected_obj->name);
return true;
case Common::EVENT_KEYDOWN:
if (_active && event.kbd.keycode == Common::KEYCODE_ESCAPE) {
activate(false);
return true;
}
return false;
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
return _active;
default:
return false;
}
}
void Inventory::Item::free() {
animation.free();
surface.free();
}
void Inventory::Item::render(Inventory * inventory, InventoryObject *obj, Graphics::Surface * dst) {
Resources * res = Resources::instance();
rect.render(dst, hovered? 233: 234);
if (obj->animated) {
if (animation.empty()) {
debug(0, "loading item %d from offset %x", obj->id, inventory->offset[obj->id - 1]);
inventory->items->seek(inventory->offset[obj->id - 1]);
animation.load(inventory->items, Animation::TypeInventory);
}
Surface * s = animation.currentFrame();
if (s != NULL)
s->render(dst, rect.left + 1, rect.top + 1);
} else {
if (surface.empty()) {
debug(0, "loading item %d from offset %x", obj->id, inventory->offset[obj->id - 1]);
inventory->items->seek(inventory->offset[obj->id - 1]);
surface.load(inventory->items, Surface::TypeOns);
}
surface.render(dst, rect.left + 1, rect.top + 1);
}
Common::String name;
if (inventory->selected_obj && inventory->selected_obj != inventory->hovered_obj) {
name = inventory->selected_obj->name;
name += " & ";
}
name += obj->name;
if (hovered) {
int w = res->font7.render(NULL, 0, 0, name, true);
res->font7.render(dst, (320 - w) / 2, 180, name, true);
}
}
void Inventory::render(Graphics::Surface * surface) {
if (!_active)
return;
background.render(surface);
Resources * res = Resources::instance();
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 6; x++) {
int idx = x + 6 * y;
byte item = inventory[idx];
if (item == 0)
continue;
//debug(0, "%d,%d -> %u", x0, y0, item);
InventoryObject * obj = (InventoryObject *)res->dseg.ptr(READ_LE_UINT16(objects + item * 2));
graphics[idx].render(this, obj, surface);
}
}
}

View File

@ -0,0 +1,84 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/objects.h $
* $Id: objects.h 172 2009-08-11 08:06:58Z megath $
*/
#ifndef TEENAGENT_INVENTORY_H__
#define TEENAGENT_INVENTORY_H__
#include "surface.h"
#include "animation.h"
#include "common/events.h"
#include "objects.h"
namespace TeenAgent {
struct InventoryObject;
class TeenAgentEngine;
class Inventory {
public:
void init(TeenAgentEngine * engine);
void render(Graphics::Surface * surface);
void clear();
void add(byte item);
bool has(byte item) const;
void remove(byte item);
void activate(bool a) { _active = a; }
bool active() const { return _active; }
bool processEvent(const Common::Event &event);
InventoryObject *selectedObject() { return selected_obj; }
void resetSelectedObject() { selected_obj = NULL; }
private:
TeenAgentEngine *_engine;
Surface background;
Common::SeekableReadStream *items;
uint16 offset[92];
byte *objects;
byte *inventory;
struct Item {
Animation animation;
Surface surface;
Rect rect;
bool hovered;
Item() : hovered(false) {}
void free();
void render(Inventory *inventory, InventoryObject *obj, Graphics::Surface * surface);
} graphics[24];
bool _active;
Common::Point mouse;
int hovered;
InventoryObject *hovered_obj, *selected_obj;
};
}
#endif

View File

@ -0,0 +1,26 @@
MODULE := engines/teenagent
MODULE_OBJS := \
detection.o \
teenagent.o \
resources.o \
pack.o \
segment.o \
scene.o \
animation.o \
font.o \
surface.o \
actor.o \
callbacks.o \
inventory.o \
objects.o \
music.o \
dialog.o
# This module can be built as a plugin
ifeq ($(ENABLE_TEENAGENT), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk

162
engines/teenagent/music.cpp Normal file
View File

@ -0,0 +1,162 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/old_engine/music.cpp $
* $Id: music.cpp 121 2009-08-02 20:04:53Z megath $
*
*/
#include "music.h"
#include "resources.h"
using namespace TeenAgent;
static uint32 noteToPeriod[3][12] = {
{855, 807, 761, 720, 678, 640, 604, 569, 537, 508, 480, 453},
{428, 404, 381, 360, 338, 320, 301, 285, 269, 254, 239, 226},
{214, 201, 189, 179, 170, 160, 151, 143, 135, 127, 120, 113}
};
MusicPlayer::MusicPlayer() : Paula(false, 44100, 5000), _id(0) {
}
MusicPlayer::~MusicPlayer() {
}
bool MusicPlayer::load(int id) {
Resources * res = Resources::instance();
Common::SeekableReadStream *stream = res->mmm.getStream(id);
if (stream == NULL)
return false;
char header[4];
stream->read(header, 4);
//check header?
memset(_samples, 0, sizeof(_samples));
// Load the samples
sampleCount = stream->readByte();
debug(0, "sampleCount = %d", sampleCount);
for (byte currSample = 0; currSample < sampleCount; currSample++) {
byte sample = stream->readByte();
// Load the sample data
byte sampleResource = ((sample >> 4) & 0x0F) * 10 + (sample & 0x0F);
debug(0, "currSample = %d, sample = 0x%02x, resource: %d", currSample, sample, sampleResource);
uint32 sampleSize = res->sam_mmm.get_size(sampleResource);
Common::SeekableReadStream *in = res->sam_mmm.getStream(sampleResource);
if (in == 0) {
warning("load: invalid sample %d (0x%02x)", sample, sample);
_samples[sample].data = NULL;
_samples[sample].size = 0;
continue;
}
byte *sampleData = new byte[sampleSize];
in->read(sampleData, sampleSize);
// Convert the sample from signed to unsigned
for (uint32 i = 0; i < sampleSize; i++)
*sampleData ^= 0x80;
delete _samples[sample].data;
_samples[sample].data = sampleData;
_samples[sample].size = sampleSize;
}
// Load the music data
_rows.clear();
Row row;
row.channels[0].sample = 0;
row.channels[1].sample = 0;
row.channels[2].sample = 0;
row.channels[0].volume = 64;
row.channels[1].volume = 64;
row.channels[2].volume = 64;
while (!stream->eos()) {
byte cmd = stream->readByte();
if ((cmd & 0xF0) == 0x50) {
row.channels[(cmd & 0x0F) - 1].sample = stream->readByte();
} else if ((cmd & 0xF0) == 0x40) {
row.channels[(cmd & 0x0F) - 1].volume = (stream->readByte() + 1) * 2;
} else {
row.channels[0].note = cmd;
row.channels[1].note = stream->readByte();
row.channels[2].note = stream->readByte();
_rows.push_back(row);
}
}
_currRow = 0;
_id = id;
return true;
}
void MusicPlayer::start() {
_currRow = 0;
startPaula();
}
void MusicPlayer::stop() {
stopPaula();
}
void MusicPlayer::interrupt() {
_currRow %= _rows.size();
Row *row = &_rows[_currRow];
for (int chn = 0; chn < 3; ++chn) {
setChannelVolume(chn, row->channels[chn].volume);
//debug(0, "row->channels[%d].volume = %d", chn, row->channels[chn].volume);
byte sample = (row->channels[chn].sample);
if (row->channels[chn].note != 0 && sample != 0) {
//debug(0, "row->channels[%d].note = %d", chn, row->channels[chn].note);
//debug(0, "row->channels[%d].sample = %d", chn, row->channels[chn].sample);
byte note = row->channels[chn].note;
if (_samples[sample].size == 0) {
warning("interrupt: invalid sample %u (0x%02x)", sample, sample);
continue;
}
setChannelData(chn, (const int8*)_samples[sample].data, NULL, _samples[sample].size, 0);
setChannelPeriod(chn, noteToPeriod[((note >> 4) & 0x0F) - 1][(note & 0x0F)]);
}
}
//debug(0, "------------------------------------------------");
++_currRow;
}

77
engines/teenagent/music.h Normal file
View File

@ -0,0 +1,77 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/old_engine/music.h $
* $Id: music.h 121 2009-08-02 20:04:53Z megath $
*
*/
#ifndef TEEN_MUSIC_H
#define TEEN_MUSIC_H
#include "sound/mods/paula.h"
namespace TeenAgent {
class MusicPlayer : public Audio::Paula {
public:
MusicPlayer();
~MusicPlayer();
bool load(int id);
int getId() const { return _id; }
void start();
void stop();
protected:
int _id;
struct Row {
struct Channel{
byte sample;
byte volume;
byte note;
Channel(): sample(0), volume(0), note(0) {}
} channels[3];
};
struct {
const byte *data;
uint32 size;
} _samples[256];
byte sampleCount;
struct {
byte volume;
const byte *data;
uint32 size;
} _channels[3];
Common::Array<Row> _rows;
uint _currRow;
void interrupt();
};
} // End of namespace Teen
#endif // TEEN_MUSIC_H

View 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.
*
* $URL: https://www.switchlink.se/svn/teen/objects.h $
* $Id: objects.h 172 2009-08-11 08:06:58Z megath $
*/
#include "objects.h"
#include "common/debug.h"
using namespace TeenAgent;
void Rect::render(Graphics::Surface *surface, uint8 color) const {
surface->hLine(left, bottom, right, color);
surface->vLine(left, bottom, top, color);
surface->hLine(left, top, right, color);
surface->vLine(right, bottom, top, color);
}
void Walkbox::dump() {
debug(0, "walkbox %02x %02x [%d, %d, %d, %d] %02x %02x %02x %02x ", unk00, unk01,
rect.left, rect.right, rect.top, rect.bottom,
unk0a, unk0b, unk0c, unk0d);
}
void Object::dump() {
debug(0, "object: %u %u [%u,%u,%u,%u], actor: [%u,%u,%u,%u], orientation: %u, name: %s", id, enabled,
rect.left, rect.top, rect.right, rect.bottom,
actor_rect.left, actor_rect.top, actor_rect.right, actor_rect.bottom,
actor_orientation, name
);
}
Common::String Object::description(const char *name) {
const char * desc = name + strlen(name) + 1;
if (*desc == 0)
return Common::String();
Common::String result;
while(*desc != 1 && *desc != 0) {
Common::String line;
while(*desc != 1 && *desc != 0) {
//debug(0, "%02x ", *desc);
line += *desc++;
}
if (line.empty())
break;
++desc;
result += line;
result += '\n';
}
if (!result.empty())
result.deleteLastChar();
else
result = "Cool.";
return result;
}
Common::String Object::description() const {
return description(name);
}
Common::String InventoryObject::description() const {
return Object::description(name);
}

104
engines/teenagent/objects.h Normal file
View File

@ -0,0 +1,104 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/objects.h $
* $Id: objects.h 282 2009-08-30 22:12:01Z megath $
*/
#ifndef TEENAGENT_OBJECTS_H__
#define TEENAGENT_OBJECTS_H__
#include "common/rect.h"
#include "graphics/surface.h"
namespace TeenAgent {
//move into separate header:
#include "common/pack-start.h" // START STRUCT PACKING
struct Rect {
uint16 left, top, right, bottom;
inline bool in(const Common::Point &point) const {
return point.x >= left && point.x <= right && point.y >= top && point.y <= bottom;
}
inline Common::Point center() const {
return Common::Point((right + left) / 2, (bottom + top) / 2);
}
inline bool valid() const {
return left < 320 && right < 320 && top < 200 && bottom < 200;
}
void render(Graphics::Surface *surface, uint8 color) const;
void dump() {
debug(0, "rect[%u, %u, %u, %u]", left, top, right, bottom);
}
void clear() {
left = top = right = bottom = 0;
}
} PACKED_STRUCT;
struct Object {
byte id;
Rect rect;
Rect actor_rect;
byte actor_orientation;
byte enabled;
char name[1];
enum {ActorUp = 1, ActorRight = 2, ActorDown = 3, ActorLeft = 4 };
void dump();
static Common::String description(const char *name);
Common::String description() const;
} PACKED_STRUCT;
struct InventoryObject {
byte id;
byte animated;
char name[1];
Common::String description() const;
} PACKED_STRUCT;
struct UseObject {
byte inventory_id;
byte object_id;
byte unk02;
uint16 x, y;
uint16 callback;
} PACKED_STRUCT;
struct Walkbox {
byte unk00;
byte unk01;
Rect rect;
byte unk0a;
byte unk0b;
byte unk0c;
byte unk0d;
void dump();
} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
}
#endif

View File

@ -0,0 +1,83 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/pack.cpp $
* $Id: pack.cpp 182 2009-08-11 21:16:14Z megath $
*/
#include "pack.h"
#include "common/util.h"
#include "common/debug.h"
using namespace TeenAgent;
Pack::Pack() : count(0), offsets(0) {}
Pack::~Pack() {
close();
}
void Pack::close() {
delete[] offsets;
offsets = NULL;
file.close();
}
void Pack::open(const Common::String &filename) {
file.open(filename);
count = file.readUint32LE();
debug(0, "opened %s, found %u entries", filename.c_str(), count);
offsets = new uint32[count + 1];
for(uint32 i = 0; i <= count; ++i) {
offsets[i] = file.readUint32LE();
//debug(0, "%d: %06x", i, offsets[i]);
}
/* for(uint32 i = 0; i < count; ++i) {
debug(0, "%d: len = %d", i, offsets[i + 1] - offsets[i]);
}
*/
}
uint32 Pack::get_size(uint32 id) const {
if (id < 1 || id > count)
return 0;
return offsets[id] - offsets[id - 1];
}
uint32 Pack::read(uint32 id, byte *dst, uint32 size) const {
if (id < 1 || id > count)
return 0;
file.seek(offsets[id - 1]);
uint32 rsize = offsets[id] - offsets[id - 1];
uint32 r = file.read(dst, MIN(rsize, size));
//debug(0, "read(%u, %u) = %u", id, size, r);
return r;
}
Common::SeekableReadStream * Pack::getStream(uint32 id) const {
if (id < 1 || id > count)
return 0;
debug(0, "stream: %04x-%04x", offsets[id - 1], offsets[id]);
return new Common::SeekableSubReadStream(&file, offsets[id - 1], offsets[id], false);
}

49
engines/teenagent/pack.h Normal file
View File

@ -0,0 +1,49 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/pack.h $
* $Id: pack.h 182 2009-08-11 21:16:14Z megath $
*/
#ifndef TEENAGENT_PACK_H__
#define TEENAGENT_PACK_H__
#include "common/file.h"
namespace TeenAgent {
class Pack {
mutable Common::File file;
uint32 count;
uint32 *offsets;
public:
Pack();
~Pack();
void open(const Common::String &filename);
void close();
uint32 get_size(uint32 id) const;
uint32 read(uint32 id, byte *dst, uint32 size) const;
Common::SeekableReadStream * getStream(uint32 id) const;
};
}
#endif

View File

@ -0,0 +1,144 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/resources.cpp $
* $Id: resources.cpp 274 2009-08-25 21:04:54Z megath $
*/
#include "resources.h"
using namespace TeenAgent;
Resources::Resources() {}
Resources * Resources::instance() {
static Resources i;
return &i;
}
void Resources::deinit() {
varia.close();
off.close();
on.close();
ons.close();
lan000.close();
lan500.close();
mmm.close();
sam_mmm.close();
sam_sam.close();
}
void Resources::loadArchives() {
off.open("off.res");
varia.open("varia.res");
on.open("on.res");
ons.open("ons.res");
lan000.open("lan_000.res");
lan500.open("lan_500.res");
mmm.open("mmm.res");
sam_mmm.open("sam_mmm.res");
sam_sam.open("sam_sam.res");
font7.load(7);
Common::File exe;
if (!exe.open("Teenagnt.exe")) {
error("cannot open exe file");
return;
}
exe.seek(0x0200);
cseg.read(&exe, 0xb3b0); //code
exe.seek(0xb5b0);
dseg.read(&exe, 0xe790); //data
exe.seek(0x1c890);
eseg.read(&exe, 0x8be2);
exe.close();
}
void Resources::loadOff(Graphics::Surface &surface, byte * palette, int id) {
uint32 size = off.get_size(id);
if (size == 0) {
error("invalid background %d", id);
return;
}
byte buf[64768];
off.read(id, buf, sizeof(buf));
byte * src = buf;
byte * dst = (byte *)surface.pixels;
memcpy(dst, src, 64000);
memcpy(palette, buf + 64000, 768);
}
Common::SeekableReadStream * Resources::loadLan(uint32 id) const {
return id <= 500? loadLan000(id): lan500.getStream(id - 500);
}
Common::SeekableReadStream * Resources::loadLan000(uint32 id) const {
switch(id) {
case 81:
if (dseg.get_byte(0xDBAD))
return lan500.getStream(160);
break;
case 137:
if (dseg.get_byte(0xDBC5) == 1) {
if (dseg.get_byte(0xDBC6) == 1)
return lan500.getStream(203);
else
return lan500.getStream(202);
}
break;
case 25:
if (dseg.get_byte(0xDBDF) == 2) {
return lan500.getStream(332);
}
break;
case 37:
if (dseg.get_byte(0xdbe2) == 1) {
return lan500.getStream(351);
} else if (dseg.get_byte(0xdbe2) == 2) {
return lan500.getStream(364);
}
break;
case 29:
if (dseg.get_byte(0xDBE7) == 1) {
return lan500.getStream(380);
}
case 30:
if (dseg.get_byte(0xDBE7) == 1) {
return lan500.getStream(381);
}
case 42:
if (dseg.get_byte(0xDBEC) == 1) {
return lan500.getStream(400);
}
}
return lan000.getStream(id);
}

View File

@ -0,0 +1,56 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/resources.h $
* $Id: resources.h 260 2009-08-19 07:29:19Z megath $
*/
#ifndef TEENAGENT_RESOURCES_H__
#define TEENAGENT_RESOURCES_H__
#include "pack.h"
#include "segment.h"
#include "font.h"
#include "graphics/surface.h"
namespace TeenAgent {
class Resources {
protected:
Resources();
public:
static Resources * instance();
void loadArchives();
void deinit();
void loadOff(Graphics::Surface &surface, byte *palette, int id);
Common::SeekableReadStream * loadLan(uint32 id) const;
Common::SeekableReadStream * loadLan000(uint32 id) const;
//void loadOn(Graphics::Surface &surface, int id, uint16 &dst, uint16 * flags);
//void loadOns(Graphics::Surface &surface, int id, uint16 &dst);
Pack varia, off, on, ons, lan000, lan500, mmm, sam_mmm, sam_sam;
Segment cseg, dseg, eseg;
Font font7;
};
}
#endif

511
engines/teenagent/scene.cpp Normal file
View File

@ -0,0 +1,511 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/scene.cpp $
* $Id: scene.cpp 303 2009-09-03 20:09:57Z megath $
*/
#include "scene.h"
#include "resources.h"
#include "surface.h"
#include "common/debug.h"
#include "objects.h"
#include "teenagent.h"
#include "dialog.h"
#include "music.h"
using namespace TeenAgent;
Scene::Scene() : _engine(NULL),
_system(NULL),
_id(0), ons(0), walkboxes(0),
orientation(Object::ActorRight),
current_event(SceneEvent::None),
sound_id(0), sound_delay(0) {}
void Scene::warp(const Common::Point & _point, byte o) {
Common::Point point(_point);
destination = position = position0 = point;
progress = 0; progress_total = 1;
if (o)
orientation = o;
}
void Scene::moveTo(const Common::Point & _point, byte orient, bool validate) {
Common::Point point(_point);
debug(0, "moveTo(%d, %d, %u)", point.x, point.y, orient);
if (validate) {
for(byte i = 0; i < walkboxes; ++i) {
if (walkbox[i]->rect.in(point)) {
debug(0, "bumped into walkbox %u", i);
return;
}
}
}
if (point == position) {
if (orient != 0)
orientation = orient;
nextEvent();
return;
}
destination = point;
orientation = orient;
position0 = position;
progress_total = 1 + sqrt((float)position.sqrDist(destination)) / 10;
progress = 0;
}
void Scene::init(TeenAgentEngine *engine, OSystem * system) {
_engine = engine;
_system = system;
Resources * res = Resources::instance();
Common::SeekableReadStream * s = res->varia.getStream(1);
if (s == NULL)
error("invalid resource data");
teenagent.load(s, Animation::TypeVaria);
s = res->varia.getStream(2);
if (s == NULL)
error("invalid resource data");
teenagent_idle.load(s, Animation::TypeVaria);
}
byte *Scene::getOns(int id) {
Resources * res = Resources::instance();
return res->dseg.ptr(res->dseg.get_word(0xb4f5 + (id - 1) * 2));
}
byte * Scene::getLans(int id) {
Resources * res = Resources::instance();
return res->dseg.ptr(0xd89e + (id - 1) * 4);
}
void Scene::loadOns() {
debug(0, "loading ons animation");
Resources * res = Resources::instance();
uint16 addr = res->dseg.get_word(0xb4f5 + (_id - 1) * 2);
//debug(0, "ons index: %04x", addr);
ons_count = 0;
byte b;
byte on_id[16];
while((b = res->dseg.get_byte(addr)) != 0xff) {
debug(0, "on: %04x = %02x", addr, b);
++addr;
if (b == 0)
continue;
on_id[ons_count++] = b;
}
delete[] ons;
ons = NULL;
if (ons_count > 0) {
ons = new Surface[ons_count];
for(uint32 i = 0; i < ons_count; ++i) {
Common::SeekableReadStream * s = res->ons.getStream(on_id[i]);
if (s != NULL)
ons[i].load(s, Surface::TypeOns);
}
}
}
void Scene::loadLans() {
debug(0, "loading lans animation");
Resources * res = Resources::instance();
//load lan000
byte * table_27 = res->dseg.ptr(0x32C7);
memset(table_27, 0, 27 * 4);
for (int i = 0; i < 4; ++i) {
animations[i].free();
uint16 bx = 0xd89e + (_id - 1) * 4 + i;
byte bxv = res->dseg.get_byte(bx);
debug(0, "lan: [%04x] = %02x", bx, bxv);
if (bxv == 0)
continue;
Common::SeekableReadStream * s = res->loadLan000(4 * (_id - 1) + i + 1);
if (s != NULL) {
animations[i].load(s, Animation::TypeLan);
if (bxv != 0 && bxv != 0xff)
animations[i].id = bxv;
delete s;
}
//uint16 bp = res->dseg.get_word();
}
}
void Scene::init(int id, const Common::Point &pos) {
debug(0, "init(%d)", id);
_id = id;
if (background.pixels == NULL)
background.create(320, 200, 1);
warp(pos);
Resources * res = Resources::instance();
res->loadOff(background, palette, id);
if (id == 24) {
//dark scene
if (res->dseg.get_byte(0xDBA4) != 1) {
//dim down palette
uint i;
for(i = 0; i < 624; ++i) {
palette[i] = palette[i] > 0x20? palette[i] - 0x20: 0;
}
for(i = 726; i < 768; ++i) {
palette[i] = palette[i] > 0x20? palette[i] - 0x20: 0;
}
}
}
setPalette(_system, palette, 4);
Common::SeekableReadStream *stream = res->on.getStream(id);
on.load(stream, Surface::TypeOn);
delete stream;
loadOns();
loadLans();
byte * walkboxes_base = res->dseg.ptr(READ_LE_UINT16(res->dseg.ptr(0x6746 + (id - 1) * 2)));
walkboxes = *walkboxes_base++;
debug(0, "found %d walkboxes", walkboxes);
for (byte i = 0; i < walkboxes; ++i) {
walkbox[i] = (Walkbox *)(walkboxes_base + 14 * i);
walkbox[i]->dump();
}
if (id == 23 && res->dseg.get_byte(0xdbee) == 1) {
//talked to anne, lovers music
if (_engine->music->getId() != 6)
_engine->music->load(6);
} else {
//check music
int now_playing = _engine->music->getId();
if (now_playing != res->dseg.get_byte(0xDB90))
_engine->music->load(res->dseg.get_byte(0xDB90));
}
}
void Scene::playAnimation(byte idx, uint id) {
assert(idx < 4);
Common::SeekableReadStream * s = Resources::instance()->loadLan(id + 1);
if (s == NULL)
error("playing animation %u failed", id);
custom_animations[idx].load(s);
custom_animations[idx].loop = idx == 3; //looping face animation.
}
void Scene::push(const SceneEvent &event) {
//debug(0, "push");
//event.dump();
events.push_back(event);
}
bool Scene::processEvent(const Common::Event &event) {
if (!message.empty()) {
if (
event.type == Common::EVENT_LBUTTONDOWN ||
event.type == Common::EVENT_RBUTTONDOWN
) {
message.clear();
custom_animations[3].free();
nextEvent();
return true;
}
}
return false;
}
bool Scene::render(OSystem * system) {
//render background
bool busy = false;
system->copyRectToScreen((const byte *)background.pixels, background.pitch, 0, 0, background.w, background.h);
Graphics::Surface * surface = system->lockScreen();
if (ons != NULL) {
for(uint32 i = 0; i < ons_count; ++i) {
Surface* s = ons + i;
if (s != NULL)
s->render(surface);
}
}
for(int i = 3; i >= 0; --i) {
Animation &a = animations[i];
Surface *s = a.currentFrame();
if (s == NULL)
continue;
s->render(surface);
if (a.id == 0)
continue;
Object * obj = getObject(a.id);
if (obj != NULL) {
obj->rect.left = s->x;
obj->rect.top = s->y;
obj->rect.right = s->w + s->x;
obj->rect.bottom = s->h + s->y;
//obj->dump();
}
}
//render on
if (on.pixels != NULL) {
on.render(surface);
}
bool hide_actor = false;
bool got_any_animation = false;
for(int i = 3; i >= 0; --i) {
Animation &a = custom_animations[i];
Surface *s = a.currentFrame();
if (s == NULL) {
if (!a.empty() && current_event.type == SceneEvent::PlayAnimation) {
debug(0, "animation %u stopped", current_event.animation);
a.free();
nextEvent();
i = -1;
}
continue;
}
s->render(surface);
if (i == 0) {
//debug(0, "animation active @%u,%u, hiding actor", s->x, s->y);
hide_actor = true;
}
busy = true;
got_any_animation = true;
}
if (current_event.type == SceneEvent::WaitForAnimation && !got_any_animation) {
nextEvent();
}
if (destination != position) {
Common::Point dp(destination.x - position0.x, destination.y - position0.y);
int o;
if (ABS(dp.x) > ABS(dp.y))
o = dp.x > 0? Object::ActorRight: Object::ActorLeft;
else
o = dp.y > 0? Object::ActorDown: Object::ActorUp;
position.x = position0.x + dp.x * progress / progress_total;
position.y = position0.y + dp.y * progress / progress_total;
teenagent.render(surface, position, o, 1);
++progress;
if (progress >= progress_total) {
position = destination;
if (orientation == 0)
orientation = o; //save last orientation
nextEvent();
} else
busy = true;
} else if (!hide_actor) {
teenagent.render(surface, position, orientation, 0);
}
busy |= processEventQueue();
//if (!current_event.empty())
// current_event.dump();
for (byte i = 0; i < walkboxes; ++i) {
Walkbox * w = walkbox[i];
w->rect.render(surface, 0xd0 + i);
}
if (!message.empty()) {
Resources::instance()->font7.render(surface, message_pos.x, message_pos.y, message);
busy = true;
}
system->unlockScreen();
if (sound_id != 0 && sound_delay != 0) {
if (--sound_delay == 0) {
debug(0, "delayed sound %u started", sound_id);
_engine->playSoundNow(sound_id);
sound_id = 0;
}
}
return busy;
}
bool Scene::processEventQueue() {
while (!events.empty() && current_event.empty()) {
//debug(0, "processing next event");
current_event = events.front();
events.pop_front();
switch(current_event.type) {
case SceneEvent::SetOn: {
byte * ptr = getOns(current_event.scene == 0? _id: current_event.scene);
debug(0, "on[%u] = %02x", current_event.ons - 1, current_event.color);
ptr[current_event.ons - 1] = current_event.color;
loadOns();
current_event.clear();
} break;
case SceneEvent::SetLan: {
if (current_event.lan != 0) {
debug(0, "lan[%u] = %02x", current_event.lan - 1, current_event.color);
byte * ptr = getLans(current_event.scene == 0? _id: current_event.scene);
ptr[current_event.lan - 1] = current_event.color;
}
loadLans();
current_event.clear();
} break;
case SceneEvent::LoadScene: {
init(current_event.scene, current_event.dst);
current_event.clear();
} break;
case SceneEvent::Walk: {
if (current_event.color != 0) {
warp(current_event.dst, current_event.orientation);
current_event.clear();
} else
moveTo(current_event.dst, current_event.orientation);
} break;
case SceneEvent::Message: {
//debug(0, "pop(%04x)", current_event.message);
message = current_event.message;
message_pos = messagePosition(message, position);
} break;
case SceneEvent::PlayAnimation: {
debug(0, "playing animation %u", current_event.animation);
playAnimation(current_event.color & 0x7f /*slot actually :)*/, current_event.animation);
if (current_event.color & 0x80)
nextEvent();
} break;
case SceneEvent::PlayMusic: {
debug(0, "setting music %u", current_event.music);
_engine->setMusic(current_event.music);
Resources::instance()->dseg.set_byte(0xDB90, current_event.music);
current_event.clear();
} break;
case SceneEvent::PlaySound: {
debug(0, "playing sound %u, delay: %u", current_event.sound, current_event.color);
if (current_event.color == 0) {
_engine->playSoundNow(current_event.sound);
} else {
sound_id = current_event.sound;
sound_delay = current_event.color;
}
current_event.clear();
} break;
case SceneEvent::EnableObject: {
debug(0, "%s object #%u", current_event.color?"enabling":"disabling", current_event.object - 1);
Object * obj = getObject(current_event.object - 1, current_event.scene == 0? _id: current_event.scene);
obj->enabled = current_event.color;
current_event.clear();
} break;
case SceneEvent::WaitForAnimation:
debug(0, "waiting for the animation");
break;
default:
error("empty/unhandler event[%d]", (int)current_event.type);
}
}
return !current_event.empty();
}
void Scene::setPalette(OSystem *system, const byte * buf, unsigned mul) {
byte p[1024];
memset(p, 0, 1024);
for(int i = 0; i < 256; ++i) {
for(int c = 0; c < 3; ++c)
p[i * 4 + c] = buf[i * 3 + c] * mul;
}
system->setPalette(p, 0, 256);
}
Object * Scene::getObject(int id, int scene_id) {
if (scene_id == 0)
scene_id = _id;
Resources * res = Resources::instance();
uint16 addr = res->dseg.get_word(0x7254 + (scene_id - 1) * 2);
//debug(0, "object base: %04x, x: %d, %d", addr, point.x, point.y);
uint16 object = res->dseg.get_word(addr + 2 * id - 2);
Object *obj = (Object *)res->dseg.ptr(object);
return obj;
}
Common::Point Scene::messagePosition(const Common::String &str, const Common::Point & position) {
Resources * res = Resources::instance();
uint w = res->font7.render(NULL, 0, 0, str);
Common::Point message_pos = position;
message_pos.x -= w / 2;
message_pos.y -= 62;
if (message_pos.x + w > 320)
message_pos.x = 320 - w;
if (message_pos.x < 0)
message_pos.x = 0;
return message_pos;
}
void Scene::displayMessage(const Common::String &str) {
debug(0, "displayMessage: %s", str.c_str());
message = str;
message_pos = messagePosition(str, position);
}
void Scene::clear() {
events.clear();
current_event.clear();
}

166
engines/teenagent/scene.h Normal file
View File

@ -0,0 +1,166 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/scene.h $
* $Id: scene.h 296 2009-09-01 19:55:58Z megath $
*/
#ifndef TEENAGENT_SCENE_H__
#define TEENAGENT_SCENE_H__
#include "surface.h"
#include "actor.h"
#include "common/system.h"
#include "common/list.h"
namespace TeenAgent {
struct Walkbox;
struct Object;
class TeenAgentEngine;
class Dialog;
struct SceneEvent {
enum Type {
None, Message, Walk, PlayAnimation,
LoadScene, SetOn, SetLan, PlayMusic,
PlaySound, EnableObject, WaitForAnimation
} type;
Common::String message;
byte color;
uint16 animation;
byte orientation;
Common::Point dst;
byte scene; //fixme: put some of these to the union?
byte ons;
byte lan;
byte music;
byte sound;
byte object;
SceneEvent(Type type_) :
type(type_), message(), color(0xd1), animation(0), orientation(0), dst(),
scene(0), ons(0), lan(0), music(0), sound(0), object(0) {}
void clear() {
type = None;
message.clear();
color = 0xd1;
orientation = 0;
animation = 0;
dst.x = dst.y = 0;
scene = 0;
ons = 0;
lan = 0;
music = 0;
sound = 0;
object = 0;
}
inline bool empty() const {
return type == None;
}
void dump() const {
debug(0, "event[%d]: %s[%02x], animation: %u, dst: (%d, %d) [%u], scene: %u, ons: %u, lan: %u, object: %u, music: %u, sound: %u",
(int)type, message.c_str(), color, animation, dst.x, dst.y, orientation, scene, ons, lan, object, music, sound
);
}
};
class Scene {
public:
Scene();
void init(TeenAgentEngine *engine, OSystem * system);
void init(int id, const Common::Point &pos);
bool render(OSystem * system);
int getId() const { return _id; }
void warp(const Common::Point & point, byte orientation = 0);
void moveTo(const Common::Point & point, byte orientation = 0, bool validate = 0);
Common::Point getPosition() const { return position; }
void displayMessage(const Common::String &str);
void setOrientation(uint8 o) { orientation = o; }
void playAnimation(byte idx, uint id);
void push(const SceneEvent &event);
bool processEvent(const Common::Event &event);
void clear();
byte * getOns(int id);
byte * getLans(int id);
bool eventRunning() const { return !current_event.empty(); }
Walkbox *getWalkbox(byte id) { return walkbox[id]; }
Object * getObject(int id, int scene_id = 0);
private:
void loadOns();
void loadLans();
byte palette[768];
void setPalette(OSystem *system, const byte * palette, unsigned mul = 1);
static Common::Point messagePosition(const Common::String &str, const Common::Point & position);
bool processEventQueue();
inline void nextEvent() {
current_event.clear();
processEventQueue();
}
TeenAgentEngine *_engine;
OSystem * _system;
int _id;
Graphics::Surface background;
Surface on;
Surface *ons;
uint32 ons_count;
Animation animations[4], custom_animations[4];
Actor teenagent, teenagent_idle;
Common::Point position0, position, destination;
int progress, progress_total;
uint8 orientation;
byte walkboxes;
Walkbox * walkbox[255];
Common::String message;
Common::Point message_pos;
typedef Common::List<SceneEvent> EventList;
EventList events;
SceneEvent current_event;
byte sound_id, sound_delay;
};
}
#endif

View File

@ -0,0 +1,37 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/segment.cpp $
* $Id: segment.cpp 188 2009-08-12 07:22:11Z megath $
*/
#include "segment.h"
void Segment::read(Common::ReadStream *stream, uint32 s) {
_size = s;
_data = new byte[_size];
stream->read(_data, _size);
}
Segment::~Segment() {
delete[] _data;
}

View File

@ -0,0 +1,80 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/segment.h $
* $Id: segment.h 188 2009-08-12 07:22:11Z megath $
*/
#ifndef TEENAGENT_SEGMENT_H__
#define TEENAGENT_SEGMENT_H__
#include "common/stream.h"
#include "common/endian.h"
class Segment {
uint32 _size;
byte * _data;
public:
Segment() : _size(0), _data(0) {}
~Segment();
void read(Common::ReadStream *s, uint32 _size);
inline byte get_byte(uint32 offset) const {
assert(offset < _size);
return _data[offset];
}
inline uint16 get_word(uint32 offset) const {
assert(offset + 1 < _size);
return READ_LE_UINT16(_data + offset);
}
inline uint32 get_quad(uint32 offset) const {
assert(offset + 3 < _size);
return READ_LE_UINT32(_data + offset);
}
inline void set_byte(uint32 offset, byte v) const {
assert(offset < _size);
_data[offset] = v;
}
inline void set_word(uint32 offset, uint16 v) const {
assert(offset + 1 < _size);
return WRITE_LE_UINT16(_data + offset, v);
}
inline void set_quad(uint32 offset, uint32 v) const {
assert(offset + 3 < _size);
return WRITE_LE_UINT32(_data + offset, v);
}
const byte * ptr(uint32 addr) const {
assert(addr < _size);
return _data + addr;
}
byte * ptr(uint32 addr) {
assert(addr < _size);
return _data + addr;
}
uint size() const { return _size; }
};
#endif

View File

@ -0,0 +1,95 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/surface.cpp $
* $Id: surface.cpp 214 2009-08-14 06:09:26Z megath $
*/
#include "surface.h"
#include "pack.h"
#include "common/stream.h"
#include "common/debug.h"
using namespace TeenAgent;
Surface::Surface() : x(0), y(0) {
memset(flags, 0, sizeof(flags));
}
void Surface::load(Common::SeekableReadStream *stream, Type type) {
//debug(0, "load()");
free();
x = y = 0;
memset(flags, 0, sizeof(flags));
if (type == TypeOn) {
byte fn = stream->readByte();
if (stream->eos())
return;
for(byte i = 0; i < fn; ++i) {
flags[i] = stream->readUint16LE();
debug(0, "flags[%u] = %u (0x%04x)", i, flags[i], flags[i]);
}
}
uint16 w_ = stream->readUint16LE();
uint16 h_ = stream->readUint16LE();
if (type != TypeLan) {
uint16 pos = stream->readUint16LE();
x = pos % 320;
y = pos / 320;
}
//debug(0, "declared info: %ux%u (%04xx%04x) -> %u,%u", w_, h_, w_, h_, x, y);
if (stream->eos() || w_ == 0)
return;
if (w_ * h_ > stream->size()) {//rough but working
debug(0, "invalid surface %ux%u -> %u,%u", w_, h_, x, y);
return;
}
//debug(0, "creating surface %ux%u -> %u,%u", w_, h_, x, y);
create(w_, h_, 1);
stream->read(pixels, w_ * h_);
}
void Surface::render(Graphics::Surface * surface, int dx, int dy, bool mirror) {
assert(x + w <= surface->w);
assert(y + h <= surface->h);
byte *src = (byte *)pixels;
byte *dst = (byte *)surface->getBasePtr(dx + x, dy + y);
for(int i = 0; i < h; ++i) {
for(int j = 0; j < w; ++j) {
byte p = src[j];
if (p != 0xff)
dst[mirror? w - j - 1: j] = p;
}
dst += surface->pitch;
src += pitch;
}
}

View File

@ -0,0 +1,52 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/surface.h $
* $Id: surface.h 154 2009-08-10 20:10:23Z megath $
*/
#ifndef TAGET_SURFACE_H__
#define TAGET_SURFACE_H__
#include "graphics/surface.h"
#include "common/stream.h"
namespace TeenAgent {
class Pack;
class Surface : public Graphics::Surface {
public:
enum Type {TypeOn, TypeOns, TypeLan};
uint16 flags[255];
uint16 x, y;
Surface();
void load(Common::SeekableReadStream * stream, Type type);
void render(Graphics::Surface * surface, int dx = 0, int dy = 0, bool mirror = false);
bool empty() const { return pixels == NULL; }
};
}
#endif

View File

@ -0,0 +1,484 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/tagent.cpp $
* $Id: tagent.cpp 304 2009-09-03 20:10:22Z megath $
*/
#include "teenagent/teenagent.h"
#include "common/system.h"
#include "common/events.h"
#include "common/debug.h"
#include "common/savefile.h"
#include "common/config-manager.h"
#include "sound/mixer.h"
#include "scene.h"
#include "objects.h"
#include "music.h"
using namespace TeenAgent;
TeenAgentEngine::TeenAgentEngine(OSystem * system) : Engine(system), action(ActionNone) {
music = new MusicPlayer();
}
void TeenAgentEngine::processObject() {
if (dst_object == NULL)
return;
Resources * res = Resources::instance();
switch (action) {
case ActionExamine: {
byte * dcall = res->dseg.ptr(0xb5ce);
dcall = res->dseg.ptr(READ_LE_UINT16(dcall + scene->getId() * 2 - 2));
dcall += 2 * dst_object->id - 2;
uint16 callback = READ_LE_UINT16(dcall);
if (callback == 0) {
Common::String desc = dst_object->description();
scene->displayMessage(desc);
//debug(0, "%s[%u]: description: %s", current_object->name, current_object->id, desc.c_str());
break;
}
processCallback(callback);
}
break;
case ActionUse:
{
InventoryObject *inv = inventory->selectedObject();
if (inv != NULL) {
byte * dcall = res->dseg.ptr(0xbb87);
dcall = res->dseg.ptr(READ_LE_UINT16(dcall + scene->getId() * 2 - 2));
for(UseObject * obj = (UseObject *)dcall; obj->inventory_id != 0; ++obj) {
if (obj->inventory_id == inv->id && dst_object->id == obj->object_id) {
debug(0, "combine! %u,%u", obj->x, obj->y);
//moveTo(Common::Point(obj->x, obj->y), NULL, Examine);
processCallback(obj->callback);
inventory->resetSelectedObject();
return;
}
}
//error
inventory->resetSelectedObject();
scene->displayMessage("That's no good.");
break;
} else {
byte * dcall = res->dseg.ptr(0xb89c);
dcall = res->dseg.ptr(READ_LE_UINT16(dcall + scene->getId() * 2 - 2));
dcall += 2 * dst_object->id - 2;
uint16 callback = READ_LE_UINT16(dcall);
processCallback(callback);
}
}
break;
case ActionNone:
break;
}
}
void TeenAgentEngine::use(Object *object) {
if (object == NULL || scene->eventRunning())
return;
dst_object = object;
object->rect.dump();
object->actor_rect.dump();
if (object->actor_rect.valid()) //some objects have 0xffff in left/right
scene->moveTo(object->actor_rect.center(), object->actor_orientation);
if (object->actor_orientation > 0)
scene->setOrientation(object->actor_orientation);
action = ActionUse;
}
void TeenAgentEngine::examine(const Common::Point &point, Object *object) {
if (scene->eventRunning())
return;
if (object != NULL) {
Common::Point dst = object->actor_rect.center();
debug(0, "click %d, %d, object %d, %d", point.x, point.y, dst.x, dst.y);
if (object->actor_rect.valid())
scene->moveTo(dst, object->actor_orientation);
action = ActionExamine;
dst_object = object;
} else {
debug(0, "click %d, %d", point.x, point.y);
scene->moveTo(point, 0, true);
dst_object = NULL;
action = ActionNone;
}
}
void TeenAgentEngine::deinit() {
_mixer->stopAll();
delete scene;
scene = NULL;
delete inventory;
inventory = NULL;
//delete music;
//music = NULL;
Resources::instance()->deinit();
}
Common::Error TeenAgentEngine::loadGameState(int slot) {
debug(0, "loading from slot %d", slot);
char slotStr[16];
snprintf(slotStr, sizeof(slotStr), "teenagent.%d", slot);
Common::InSaveFile *in = _saveFileMan->openForLoading(slotStr);
if (in == NULL)
return Common::kReadPermissionDenied;
Resources * res = Resources::instance();
assert(res->dseg.size() >= 0x6478 + 0x777a);
char data[0x777a];
if (in->read(data, 0x777a) != 0x777a) {
delete in;
return Common::kReadingFailed;
}
delete in;
memcpy(res->dseg.ptr(0x6478), data, sizeof(data));
scene->clear();
setMusic(Resources::instance()->dseg.get_byte(0xDB90));
int id = res->dseg.get_byte(0xB4F3);
uint16 x = res->dseg.get_word(0x64AF), y = res->dseg.get_word(0x64B1);
scene->init(id, Common::Point(x, y));
return Common::kNoError;
}
Common::Error TeenAgentEngine::saveGameState(int slot, const char *desc) {
debug(0, "saving to slot %d", slot);
char slotStr[16];
snprintf(slotStr, sizeof(slotStr), "teenagent.%d", slot);
Common::OutSaveFile *out = _saveFileMan->openForSaving(slotStr);
if (out == NULL)
return Common::kWritePermissionDenied;
Resources * res = Resources::instance();
res->dseg.set_byte(0xB4F3, scene->getId());
Common::Point pos = scene->getPosition();
res->dseg.set_word(0x64AF, pos.x);
res->dseg.set_word(0x64B1, pos.y);
assert(res->dseg.size() >= 0x6478 + 0x777a);
strncpy((char *)res->dseg.ptr(0x6478), desc, 0x16);
out->write(res->dseg.ptr(0x6478), 0x777a);
delete out;
return Common::kNoError;
}
Common::Error TeenAgentEngine::run() {
Common::EventManager * _event = _system->getEventManager();
initGraphics(320, 200, false);
scene = new Scene;
inventory = new Inventory;
Resources * res = Resources::instance();
res->loadArchives();
scene->init(this, _system);
inventory->init(this);
//res.varia.read(6, palette, sizeof(palette));
//14,15 - on type 2
//scene->init(_system, 2);
//scene->init(_system, 27);
//scene->init(_system, 28);
scene->init(10, Common::Point(136, 153));
//scene->init(_system, 1);
_system->disableCursorPalette(true);
syncSoundSettings();
music->load(4);
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, music, -1, 255, 0, true, false);
music->start();
{
int load_slot = Common::ConfigManager::instance().getInt("save_slot");
debug(0, "slot: %d", load_slot);
if (load_slot >= 0)
loadGameState(load_slot);
}
uint32 frame = 0;
Common::Event event;
Common::Point mouse;
do {
_system->showMouse(true);
uint32 t0 = _system->getMillis();
Object * current_object = findObject(scene->getId(), mouse);
while (_event->pollEvent(event)) {
if (event.type == Common::EVENT_RTL) {
deinit();
return Common::kNoError;
}
if ((!scene_busy && inventory->processEvent(event)) || scene->processEvent(event))
continue;
//debug(0, "event");
switch(event.type) {
case Common::EVENT_LBUTTONDOWN:
examine(event.mouse, current_object);
break;
case Common::EVENT_RBUTTONDOWN:
use(current_object);
break;
case Common::EVENT_MOUSEMOVE:
mouse = event.mouse;
break;
default:;
}
}
uint32 f0 = frame * 10 / 25, f1 = (frame + 1) * 10 / 25;
if (f0 != f1) {
bool b = scene->render(_system);
scene_busy = b;
if (!inventory->active() && !scene_busy && action != ActionNone) {
processObject();
action = ActionNone;
dst_object = NULL;
}
}
bool busy = inventory->active() || scene_busy;
Graphics::Surface * surface = _system->lockScreen();
if (!busy) {
InventoryObject *selected_object = inventory->selectedObject();
if (current_object || selected_object) {
Common::String name;
if (selected_object) {
name += selected_object->name;
name += " & ";
}
if (current_object)
name += current_object->name;
uint w = res->font7.render(NULL, 0, 0, name);
res->font7.render(surface, (320 - w) / 2, 180, name, true);
if (current_object) {
current_object->rect.render(surface, 0x80);
current_object->actor_rect.render(surface, 0x81);
}
}
}
inventory->render(surface);
_system->unlockScreen();
_system->updateScreen();
uint32 dt = _system->getMillis() - t0;
if (dt < 40)
_system->delayMillis(40 - dt);
++frame;
} while(!_event->shouldQuit());
deinit();
return Common::kNoError;
}
Object * TeenAgentEngine::findObject(int id, const Common::Point &point) {
Resources * res = Resources::instance();
uint16 addr = res->dseg.get_word(0x7254 + (id - 1) * 2);
//debug(0, "object base: %04x, x: %d, %d", addr, point.x, point.y);
uint16 object;
for(;(object = res->dseg.get_word(addr)) != 0; addr += 2) {
if (object == 0)
return NULL;
Object *obj = (Object *)res->dseg.ptr(object);
//obj->dump();
if (obj->enabled != 0 && obj->rect.in(point))
return obj;
}
return NULL;
}
void TeenAgentEngine::displayMessage(const Common::String &str, byte color) {
SceneEvent event(SceneEvent::Message);
event.message = str;
event.color = color;
scene->push(event);
}
void TeenAgentEngine::displayMessage(uint16 addr, byte color) {
Common::String message;
for (
const char * str = (const char *)Resources::instance()->dseg.ptr(addr);
str[0] != 0 || str[1] != 0;
++str)
{
char c = str[0];
message += c != 0 && c != -1? c: '\n';
}
displayMessage(message, color);
}
void TeenAgentEngine::moveTo(const Common::Point & dst, bool warp) {
moveTo(dst.x, dst.y);
}
void TeenAgentEngine::moveTo(uint16 x, uint16 y, bool warp) {
SceneEvent event(SceneEvent::Walk);
event.dst.x = x;
event.dst.y = y;
event.color = warp? 1: 0;
scene->push(event);
}
void TeenAgentEngine::playAnimation(uint16 id, byte slot, bool async) {
SceneEvent event(SceneEvent::PlayAnimation);
event.animation = id;
event.color = slot;
if (async)
event.color |= 0x80;
scene->push(event);
}
void TeenAgentEngine::loadScene(byte id, const Common::Point &pos, byte o) {
loadScene(id, pos.x, pos.y, o);
}
void TeenAgentEngine::loadScene(byte id, uint16 x, uint16 y, byte o) {
SceneEvent event(SceneEvent::LoadScene);
event.scene = id;
event.dst.x = x;
event.dst.y = y;
event.orientation = o;
scene->push(event);
}
void TeenAgentEngine::setOns(byte id, byte value, byte scene_id) {
SceneEvent event(SceneEvent::SetOn);
event.ons = id + 1;
event.color = value;
event.scene = scene_id;
scene->push(event);
}
void TeenAgentEngine::setLan(byte id, byte value, byte scene_id) {
if (id == 0)
error("setting lan 0 is invalid");
SceneEvent event(SceneEvent::SetLan);
event.lan = id;
event.color = value;
event.scene = scene_id;
scene->push(event);
}
void TeenAgentEngine::reloadLan() {
SceneEvent event(SceneEvent::SetLan);
event.lan = 0;
scene->push(event);
}
void TeenAgentEngine::playMusic(byte id) {
SceneEvent event(SceneEvent::PlayMusic);
event.music = id;
scene->push(event);
}
void TeenAgentEngine::playSound(byte id, byte skip_frames) {
SceneEvent event(SceneEvent::PlaySound);
event.sound = id;
event.color = skip_frames;
scene->push(event);
}
void TeenAgentEngine::enableObject(byte id, byte scene_id) {
SceneEvent event(SceneEvent::EnableObject);
event.object = id + 1;
event.color = 1;
event.scene = scene_id;
scene->push(event);
}
void TeenAgentEngine::disableObject(byte id, byte scene_id) {
SceneEvent event(SceneEvent::EnableObject);
event.object = id + 1;
event.color = 0;
event.scene = scene_id;
scene->push(event);
}
void TeenAgentEngine::waitAnimation() {
SceneEvent event(SceneEvent::WaitForAnimation);
scene->push(event);
}
void TeenAgentEngine::playSoundNow(byte id) {
Resources * res = Resources::instance();
Common::SeekableReadStream * in = res->sam_sam.getStream(id);
if (in == NULL) {
debug(0, "skipping invalid sound %u", id);
return;
}
uint size = in->size();
char *data = new char[size];
in->read(data, size);
debug(0, "playing %u samples...", size);
_mixer->playRaw(Audio::Mixer::kSFXSoundType, &_soundHandle, data, size, 11025, Audio::Mixer::FLAG_AUTOFREE);
}
void TeenAgentEngine::setMusic(byte id) {
debug(0, "starting music %u", id);
if (!music->load(id))
return;
*Resources::instance()->dseg.ptr(0xDB90) = id;
music->start();
}
bool TeenAgentEngine::hasFeature(EngineFeature f) const {
switch(f) {
case kSupportsRTL:
case kSupportsLoadingDuringRuntime:
case kSupportsSavingDuringRuntime:
return true;
default:
return false;
}
}

View File

@ -0,0 +1,110 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL: https://www.switchlink.se/svn/teen/tagent.h $
* $Id: tagent.h 304 2009-09-03 20:10:22Z megath $
*/
#ifndef TEENAGENT_ENGINE_H__
#define TEENAGENT_ENGINE_H__
#include "engines/engine.h"
#include "pack.h"
#include "resources.h"
#include "inventory.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
namespace TeenAgent {
struct Object;
class Scene;
class MusicPlayer;
class TeenAgentEngine: public Engine {
public:
enum Action { ActionNone, ActionExamine, ActionUse };
TeenAgentEngine(OSystem * system);
virtual Common::Error run();
virtual Common::Error loadGameState(int slot);
virtual Common::Error saveGameState(int slot, const char *desc);
virtual bool canLoadGameStateCurrently() { return true; }
virtual bool canSaveGameStateCurrently() { return !scene_busy; }
virtual bool hasFeature(EngineFeature f) const;
void deinit();
Object * findObject(int id, const Common::Point &point);
void examine(const Common::Point &point, Object *object);
void use(Object *object);
bool processCallback(uint16 addr);
inline Scene * getScene() { return scene; }
//event driven:
void displayMessage(uint16 addr, byte color = 0xd1);
void displayMessage(const Common::String &str, byte color = 0xd1);
void moveTo(const Common::Point & dst, bool warp = false);
void moveTo(uint16 x, uint16 y, bool warp = false);
void playAnimation(uint16 id, byte slot = 0, bool async = false);
void loadScene(byte id, const Common::Point &pos, byte o = 0);
void loadScene(byte id, uint16 x, uint16 y, byte o = 0);
void setOns(byte id, byte value, byte scene_id = 0);
void setLan(byte id, byte value, byte scene_id = 0);
void reloadLan();
void rejectMessage();
void playMusic(byte id); //schedules play
void playSound(byte id, byte skip_frames = 0);
void playSoundNow(byte id);
void enableObject(byte id, byte scene_id = 0);
void disableObject(byte id, byte scene_id = 0);
void waitAnimation();
Common::RandomSource random;
Scene *scene;
Inventory *inventory;
MusicPlayer *music;
void setMusic(byte id);
private:
void processObject();
void anotherMansionTry();
bool scene_busy;
Action action;
Object * dst_object;
Audio::AudioStream *_musicStream;
Audio::SoundHandle _musicHandle, _soundHandle;
};
}
#endif