mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-21 03:31:40 +00:00
imported teenagent engine sources.
svn-id: r43922
This commit is contained in:
parent
9b2104db32
commit
ebe1b94eb1
@ -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
1
configure
vendored
@ -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
|
||||
|
||||
|
||||
#
|
||||
|
@ -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
|
||||
|
70
engines/teenagent/actor.cpp
Normal file
70
engines/teenagent/actor.cpp
Normal 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
34
engines/teenagent/actor.h
Normal 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);
|
||||
};
|
||||
}
|
185
engines/teenagent/animation.cpp
Normal file
185
engines/teenagent/animation.cpp
Normal 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();
|
||||
}
|
64
engines/teenagent/animation.h
Normal file
64
engines/teenagent/animation.h
Normal 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
|
||||
|
1807
engines/teenagent/callbacks.cpp
Normal file
1807
engines/teenagent/callbacks.cpp
Normal file
File diff suppressed because it is too large
Load Diff
150
engines/teenagent/detection.cpp
Normal file
150
engines/teenagent/detection.cpp
Normal 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
|
106
engines/teenagent/dialog.cpp
Normal file
106
engines/teenagent/dialog.cpp
Normal 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;
|
||||
}
|
42
engines/teenagent/dialog.h
Normal file
42
engines/teenagent/dialog.h
Normal 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
142
engines/teenagent/font.cpp
Normal 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
48
engines/teenagent/font.h
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.
|
||||
*
|
||||
* $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
|
||||
|
285
engines/teenagent/inventory.cpp
Normal file
285
engines/teenagent/inventory.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
84
engines/teenagent/inventory.h
Normal file
84
engines/teenagent/inventory.h
Normal 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
|
||||
|
26
engines/teenagent/module.mk
Normal file
26
engines/teenagent/module.mk
Normal 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
162
engines/teenagent/music.cpp
Normal 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
77
engines/teenagent/music.h
Normal 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
|
86
engines/teenagent/objects.cpp
Normal file
86
engines/teenagent/objects.cpp
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.
|
||||
*
|
||||
* $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
104
engines/teenagent/objects.h
Normal 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
|
83
engines/teenagent/pack.cpp
Normal file
83
engines/teenagent/pack.cpp
Normal 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
49
engines/teenagent/pack.h
Normal 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
|
144
engines/teenagent/resources.cpp
Normal file
144
engines/teenagent/resources.cpp
Normal 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);
|
||||
}
|
56
engines/teenagent/resources.h
Normal file
56
engines/teenagent/resources.h
Normal 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
511
engines/teenagent/scene.cpp
Normal 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
166
engines/teenagent/scene.h
Normal 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
|
||||
|
37
engines/teenagent/segment.cpp
Normal file
37
engines/teenagent/segment.cpp
Normal 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;
|
||||
}
|
||||
|
80
engines/teenagent/segment.h
Normal file
80
engines/teenagent/segment.h
Normal 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
|
||||
|
95
engines/teenagent/surface.cpp
Normal file
95
engines/teenagent/surface.cpp
Normal 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;
|
||||
}
|
||||
}
|
52
engines/teenagent/surface.h
Normal file
52
engines/teenagent/surface.h
Normal 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
|
||||
|
484
engines/teenagent/teenagent.cpp
Normal file
484
engines/teenagent/teenagent.cpp
Normal 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;
|
||||
}
|
||||
}
|
110
engines/teenagent/teenagent.h
Normal file
110
engines/teenagent/teenagent.h
Normal 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user