diff options
-rw-r--r-- | engines/teenagent/callbacks.cpp | 9 | ||||
-rw-r--r-- | engines/teenagent/inventory.cpp | 19 | ||||
-rw-r--r-- | engines/teenagent/inventory.h | 3 | ||||
-rw-r--r-- | engines/teenagent/objects.cpp | 96 | ||||
-rw-r--r-- | engines/teenagent/objects.h | 71 | ||||
-rw-r--r-- | engines/teenagent/scene.cpp | 98 | ||||
-rw-r--r-- | engines/teenagent/scene.h | 11 | ||||
-rw-r--r-- | engines/teenagent/teenagent.cpp | 56 | ||||
-rw-r--r-- | engines/teenagent/teenagent.h | 6 |
9 files changed, 259 insertions, 110 deletions
diff --git a/engines/teenagent/callbacks.cpp b/engines/teenagent/callbacks.cpp index 4b70ec4649..2ea097b791 100644 --- a/engines/teenagent/callbacks.cpp +++ b/engines/teenagent/callbacks.cpp @@ -344,7 +344,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) { setOns(3, 0x5b); displayMessage(0x55db); SET_FLAG(0xdbdd, 3); - strcpy(scene->getObject(4)->name, "body"); + scene->getObject(4)->setName("body"); } else { if (Dialog::pop(scene, 0xdb5c) != 0x636b) //not 'im getting hungry' return true; @@ -1363,7 +1363,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) { case 0x58a2: Dialog::pop(scene, 0xdaba); - strcpy(scene->getObject(13)->name, (const char *)res->dseg.ptr(0x92e5)); + scene->getObject(13)->setName((const char *)res->dseg.ptr(0x92e5)); return true; case 0x58b7://Get comb from car @@ -1532,7 +1532,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) { playSound(55, 5); playActorAnimation(527); Dialog::show(scene, 0x2219); - strcpy(scene->getObject(2)->name, (const char *)res->dseg.ptr(0x9820)); + scene->getObject(2)->setName((const char *)res->dseg.ptr(0x9820)); } return true; @@ -2415,6 +2415,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) { setOns(3, 0); setOns(4, 0); scene->getWalkbox(0)->rect.clear(); + scene->getWalkbox(0)->save(); playSound(62); //patch lan, 1 displayMessage(0x3d3a); @@ -2985,7 +2986,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) { case 0x6c83: Dialog::pop(scene, 0xdb2e); - strcpy(scene->getObject(1)->name, (const char *)res->dseg.ptr(0xaa94)); + scene->getObject(1)->setName((const char *)res->dseg.ptr(0xaa94)); SET_FLAG(0xDBD1, 1); return true; diff --git a/engines/teenagent/inventory.cpp b/engines/teenagent/inventory.cpp index d07ba52e6e..d8d40f64d3 100644 --- a/engines/teenagent/inventory.cpp +++ b/engines/teenagent/inventory.cpp @@ -49,7 +49,15 @@ void Inventory::init(TeenAgentEngine *engine) { for (byte i = 0; i < offsets; ++i) { offset[i] = items->readUint16LE(); } - objects = res->dseg.ptr(0xc4a4); + + for(byte i = 0; i < 92; ++i) { + InventoryObject io; + uint16 obj_addr = res->dseg.get_word(0xc4a4 + i * 2); + if (obj_addr != 0) + io.load(res->dseg.ptr(obj_addr)); + objects.push_back(io); + } + inventory = res->dseg.ptr(0xc48d); for (int y = 0; y < 4; ++y) @@ -138,7 +146,7 @@ bool Inventory::processEvent(const Common::Event &event) { graphics[i].hovered = graphics[i].rect.in(mouse); if (graphics[i].hovered) - hovered_obj = (InventoryObject *)res->dseg.ptr(READ_LE_UINT16(objects + item * 2)); + hovered_obj = &objects[item]; } return true; @@ -149,7 +157,7 @@ bool Inventory::processEvent(const Common::Event &event) { if (selected_obj == NULL) { activate(false); - _engine->displayMessage(hovered_obj->description()); + _engine->displayMessage(hovered_obj->description); return true; } @@ -202,7 +210,7 @@ bool Inventory::processEvent(const Common::Event &event) { selected_obj = hovered_obj; if (selected_obj) - debug(0, "selected object %s", selected_obj->name); + debug(0, "selected object %s", selected_obj->name.c_str()); return true; case Common::EVENT_KEYDOWN: @@ -275,7 +283,6 @@ void Inventory::render(Graphics::Surface *surface) { return; background.render(surface); - Resources *res = Resources::instance(); for (int y = 0; y < 4; y++) { for (int x = 0; x < 6; x++) { @@ -286,7 +293,7 @@ void Inventory::render(Graphics::Surface *surface) { //debug(0, "%d,%d -> %u", x0, y0, item); - InventoryObject *obj = (InventoryObject *)res->dseg.ptr(READ_LE_UINT16(objects + item * 2)); + InventoryObject *obj = &objects[item]; graphics[idx].render(this, obj, surface); } } diff --git a/engines/teenagent/inventory.h b/engines/teenagent/inventory.h index 80e1d2ad7d..d54aa30375 100644 --- a/engines/teenagent/inventory.h +++ b/engines/teenagent/inventory.h @@ -28,6 +28,7 @@ #include "teenagent/surface.h" #include "teenagent/animation.h" #include "common/events.h" +#include "common/array.h" #include "teenagent/objects.h" namespace TeenAgent { @@ -59,7 +60,7 @@ private: Common::SeekableReadStream *items; uint16 offset[92]; - byte *objects; + Common::Array<InventoryObject> objects; byte *inventory; struct Item { Animation animation; diff --git a/engines/teenagent/objects.cpp b/engines/teenagent/objects.cpp index c49b1c7e72..90abd38b1c 100644 --- a/engines/teenagent/objects.cpp +++ b/engines/teenagent/objects.cpp @@ -22,11 +22,31 @@ * $Id$ */ -#include "teenagent/objects.h" #include "common/debug.h" +#include "common/stream.h" +#include "teenagent/objects.h" +#include "teenagent/resources.h" namespace TeenAgent { +void Rect::load(byte * src) { + _base = src; + Common::MemoryReadStreamEndian ins(src, 8); + left = ins.readUint16(); + top = ins.readUint16(); + right = ins.readUint16(); + bottom = ins.readUint16(); +} + +void Rect::save() { + assert(_base != NULL); + //Common::MemoryWriteStreamEndian out(_base, 8); //FIXME: maybe add this class to common? + WRITE_LE_UINT16(_base + 0, left); + WRITE_LE_UINT16(_base + 2, top); + WRITE_LE_UINT16(_base + 4, right); + WRITE_LE_UINT16(_base + 6, bottom); +} + void Rect::render(Graphics::Surface *surface, uint8 color) const { surface->hLine(left, bottom, right, color); surface->vLine(left, bottom, top, color); @@ -34,22 +54,38 @@ void Rect::render(Graphics::Surface *surface, uint8 color) const { surface->vLine(right, bottom, top, color); } -void Walkbox::dump() { - debug(0, "walkbox %02x %02x [%d, %d, %d, %d] %02x %02x %02x %02x ", - unk00, orientation, - rect.left, rect.right, rect.top, rect.bottom, - unk0a, unk0b, unk0c, unk0d); + +void Object::load(byte * src) { + _base = src; + + id = *src++; + + rect.load(src); + src += 8; + actor_rect.load(src); + src += 8; + + actor_orientation = *src++; + enabled = *src++; + name = (const char *)src; + description = parse_description((const char *)src); +} + +void Object::setName(const Common::String &new_name) { + assert(_base != 0); + strcpy((char *)(_base + 19), new_name.c_str()); + name = new_name; } 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 + actor_orientation, name.c_str() ); } -Common::String Object::description(const char *name) { +Common::String Object::parse_description(const char *name) { const char *desc = name + strlen(name) + 1; if (*desc == 0) return Common::String(); @@ -77,13 +113,49 @@ Common::String Object::description(const char *name) { return result; } +void InventoryObject::load(byte *src) { + _base = src; + id = *src++; + animated = *src++; + name = (const char *)src; + description = Object::parse_description((const char *)src); +} + +void UseHotspot::load(byte *src) { + Common::MemoryReadStreamEndian in(src, 9); + inventory_id = in.readByte(); + object_id = in.readByte(); + unk02 = in.readByte(); + x = in.readUint16(); + y = in.readUint16(); + callback = in.readUint16(); +} + +void Walkbox::dump() { + debug(0, "walkbox %02x %02x [%d, %d, %d, %d] %02x %02x %02x %02x ", + unk00, orientation, + rect.left, rect.right, rect.top, rect.bottom, + unk0a, unk0b, unk0c, unk0d); +} + +void Walkbox::load(byte *src) { + _base = src; -Common::String Object::description() const { - return description(name); + unk00 = *src++; + orientation = *src++; + rect.load(src); + src += 8; + unk0a = *src++; + unk0b = *src++; + unk0c = *src++; + unk0d = *src++; } -Common::String InventoryObject::description() const { - return Object::description(name); +void Walkbox::save() { + assert(_base != NULL); + _base[1] = orientation; + rect.save(); } + } // End of namespace TeenAgent diff --git a/engines/teenagent/objects.h b/engines/teenagent/objects.h index 00b147faac..e5400e7c81 100644 --- a/engines/teenagent/objects.h +++ b/engines/teenagent/objects.h @@ -27,68 +27,88 @@ #define TEENAGENT_OBJECTS_H #include "common/rect.h" +#include "common/stream.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 Rect() : left(0), top(0), right(0), bottom(0) {} - inline Rect(uint16 l, uint16 t, uint16 r, uint16 b) : left(l), top(t), right(r), bottom(b) {} + inline Rect() : left(0), top(0), right(0), bottom(0), _base(NULL) {} + + inline Rect(uint16 l, uint16 t, uint16 r, uint16 b) : left(l), top(t), right(r), bottom(b), _base(NULL) {} 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() { + + void dump() const { debug(0, "rect[%u, %u, %u, %u]", left, top, right, bottom); } - void clear() { + inline void clear() { left = top = right = bottom = 0; } -} PACKED_STRUCT; + + void load(byte *src); //8 bytes + void save(); + +protected: + byte * _base; +}; struct Object { + enum {kActorUp = 1, kActorRight = 2, kActorDown = 3, kActorLeft = 4 }; + byte id; Rect rect; Rect actor_rect; byte actor_orientation; - byte enabled; - char name[1]; - - enum {kActorUp = 1, kActorRight = 2, kActorDown = 3, kActorLeft = 4 }; + byte enabled; //19 bytes + Common::String name, description; + Object(): _base(NULL) {} void dump(); - static Common::String description(const char *name); - Common::String description() const; -} PACKED_STRUCT; + void setName(const Common::String &name); + void load(byte *addr); + + static Common::String parse_description(const char *name); + +protected: + byte * _base; +}; struct InventoryObject { byte id; byte animated; - char name[1]; - Common::String description() const; -} PACKED_STRUCT; + Common::String name, description; + + InventoryObject(): id(0), animated(0), _base(0) {} + void load(byte *addr); + +protected: + byte * _base; +}; -struct UseObject { +struct UseHotspot { byte inventory_id; byte object_id; byte unk02; uint16 x, y; uint16 callback; -} PACKED_STRUCT; + void load(byte *src); +}; struct Walkbox { byte unk00; @@ -98,10 +118,15 @@ struct Walkbox { byte unk0b; byte unk0c; byte unk0d; + + Walkbox() : _base(NULL) {} void dump(); -} PACKED_STRUCT; + void load(byte *src); + void save(); -#include "common/pack-end.h" // END STRUCT PACKING +protected: + byte * _base; +}; } // End of namespace TeenAgent diff --git a/engines/teenagent/scene.cpp b/engines/teenagent/scene.cpp index f4a8c7c5a0..e963723d96 100644 --- a/engines/teenagent/scene.cpp +++ b/engines/teenagent/scene.cpp @@ -35,7 +35,7 @@ namespace TeenAgent { Scene::Scene() : intro(false), _engine(NULL), _system(NULL), - _id(0), ons(0), walkboxes(0), + _id(0), ons(0), orientation(Object::kActorRight), current_event(SceneEvent::kNone), hide_actor(false) {} @@ -52,23 +52,24 @@ 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) { - Walkbox *w = walkbox[i]; - if (w->rect.in(point)) { + const Common::Array<Walkbox> &scene_walkboxes = walkboxes[_id - 1]; + for (byte i = 0; i < scene_walkboxes.size(); ++i) { + const Walkbox &w = scene_walkboxes[i]; + if (w.rect.in(point)) { debug(0, "bumped into walkbox %u", i); - byte o = w->orientation; + byte o = w.orientation; switch (o) { case 1: - point.y = w->rect.top - 1; + point.y = w.rect.top - 1; break; case 2: - point.x = w->rect.right + 1; + point.x = w.rect.right + 1; break; case 3: - point.y = w->rect.bottom + 1; + point.y = w.rect.bottom + 1; break; case 4: - point.x = w->rect.left - 1; + point.x = w.rect.left - 1; break; default: return; @@ -110,8 +111,56 @@ void Scene::init(TeenAgentEngine *engine, OSystem *system) { teenagent_idle.load(s, Animation::kTypeVaria); if (teenagent_idle.empty()) error("invalid mark animation"); + + //loading objects & walkboxes + objects.resize(42); + walkboxes.resize(42); + + for(byte i = 0; i < 42; ++i) { + Common::Array<Object> &scene_objects = objects[i]; + scene_objects.clear(); + + uint16 scene_table = res->dseg.get_word(0x7254 + i * 2); + uint16 object_addr; + while ((object_addr = res->dseg.get_word(scene_table)) != 0) { + Object obj; + obj.load(res->dseg.ptr(object_addr)); + //obj.dump(); + scene_objects.push_back(obj); + scene_table += 2; + } + debug(0, "scene[%u] has %u object(s)", i + 1, scene_objects.size()); + + byte *walkboxes_base = res->dseg.ptr(READ_LE_UINT16(res->dseg.ptr(0x6746 + i * 2))); + byte walkboxes_n = *walkboxes_base++; + debug(0, "scene[%u] has %u walkboxes", i + 1, walkboxes_n); + + Common::Array<Walkbox> &scene_walkboxes = walkboxes[i]; + for (byte j = 0; j < walkboxes_n; ++j) { + Walkbox w; + w.load(walkboxes_base + 14 * j); + //walkbox[i]->dump(); + scene_walkboxes.push_back(w); + } + } +} + +Object *Scene::findObject(const Common::Point &point) { + if (_id == 0) + return NULL; + + Common::Array<Object> &scene_objects = objects[_id - 1]; + + for(uint i = 0; i < scene_objects.size(); ++i) { + Object &obj = scene_objects[i]; + if (obj.enabled != 0 && obj.rect.in(point)) + return &obj; + } + return NULL; } + + byte *Scene::getOns(int id) { Resources *res = Resources::instance(); return res->dseg.ptr(res->dseg.get_word(0xb4f5 + (id - 1) * 2)); @@ -215,15 +264,6 @@ void Scene::init(int id, const Common::Point &pos) { 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(); - } - //check music int now_playing = _engine->music->getId(); @@ -407,12 +447,13 @@ bool Scene::render(OSystem *system) { //if (!current_event.empty()) // current_event.dump(); - /* - for (byte i = 0; i < walkboxes; ++i) { - Walkbox *w = walkbox[i]; - w->rect.render(surface, 0xd0 + i); + { + const Common::Array<Walkbox> & scene_walkboxes = walkboxes[_id - 1]; + for (uint i = 0; i < scene_walkboxes.size(); ++i) { + scene_walkboxes[i].rect.render(surface, 0xd0 + i); + } } - */ + } while (restart); @@ -585,16 +626,15 @@ void Scene::setPalette(OSystem *system, const byte *buf, unsigned mul) { } Object *Scene::getObject(int id, int scene_id) { + assert(id > 0); + 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); + if (scene_id == 0) + return NULL; - Object *obj = (Object *)res->dseg.ptr(object); - return obj; + return &objects[scene_id - 1][id - 1]; } Common::Point Scene::messagePosition(const Common::String &str, Common::Point position) { diff --git a/engines/teenagent/scene.h b/engines/teenagent/scene.h index dc5095822d..a19639409f 100644 --- a/engines/teenagent/scene.h +++ b/engines/teenagent/scene.h @@ -29,12 +29,10 @@ #include "teenagent/actor.h" #include "common/system.h" #include "common/list.h" +#include "teenagent/objects.h" namespace TeenAgent { -struct Walkbox; -struct Object; - class TeenAgentEngine; class Dialog; @@ -130,8 +128,9 @@ public: bool eventRunning() const { return !current_event.empty(); } - Walkbox *getWalkbox(byte id) { return walkbox[id]; } + Walkbox *getWalkbox(byte id) { return &walkboxes[_id - 1][id]; } Object *getObject(int id, int scene_id = 0); + Object *findObject(const Common::Point &point); private: void loadOns(); @@ -166,8 +165,8 @@ private: int progress, progress_total; uint8 orientation; - byte walkboxes; - Walkbox *walkbox[255]; + Common::Array<Common::Array<Object> > objects; + Common::Array<Common::Array<Walkbox> > walkboxes; Common::String message; Common::Point message_pos; diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp index c6a2fdf123..53d214950e 100644 --- a/engines/teenagent/teenagent.cpp +++ b/engines/teenagent/teenagent.cpp @@ -52,7 +52,7 @@ void TeenAgentEngine::processObject() { dcall += 2 * dst_object->id - 2; uint16 callback = READ_LE_UINT16(dcall); if (callback == 0 || !processCallback(callback)) { - Common::String desc = dst_object->description(); + Common::String desc = dst_object->description; scene->displayMessage(desc); //debug(0, "%s[%u]: description: %s", current_object->name, current_object->id, desc.c_str()); } @@ -61,14 +61,14 @@ void TeenAgentEngine::processObject() { case kActionUse: { 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); + const Common::Array<UseHotspot> &hotspots = use_hotspots[scene->getId() - 1]; + for (uint i = 0; i < hotspots.size(); ++i) { + const UseHotspot &spot = hotspots[i]; + if (spot.inventory_id == inv->id && dst_object->id == spot.object_id) { + debug(0, "combine! pos?: %u,%u", spot.x, spot.y); //moveTo(Common::Point(obj->x, obj->y), NULL, Examine); inventory->resetSelectedObject(); - if (!processCallback(TO_LE_16(obj->callback))) + if (!processCallback(TO_LE_16(spot.callback))) debug(0, "fixme! display proper description"); return; } @@ -85,7 +85,7 @@ void TeenAgentEngine::processObject() { dcall += 2 * dst_object->id - 2; uint16 callback = READ_LE_UINT16(dcall); if (!processCallback(callback)) - scene->displayMessage(dst_object->description()); + scene->displayMessage(dst_object->description); } } break; @@ -130,6 +130,24 @@ void TeenAgentEngine::examine(const Common::Point &point, Object *object) { } } +void TeenAgentEngine::init() { + Resources * res = Resources::instance(); + use_hotspots.resize(42); + byte *scene_hotspots = res->dseg.ptr(0xbb87); + for(byte i = 0; i < 42; ++i) { + Common::Array<UseHotspot> & hotspots = use_hotspots[i]; + byte * hotspots_ptr = res->dseg.ptr(READ_LE_UINT16(scene_hotspots + i * 2)); + while(*hotspots_ptr) { + UseHotspot h; + h.load(hotspots_ptr); + hotspots_ptr += 9; + hotspots.push_back(h); + } + } +} + + + void TeenAgentEngine::deinit() { _mixer->stopAll(); delete scene; @@ -138,6 +156,7 @@ void TeenAgentEngine::deinit() { inventory = NULL; //delete music; //music = NULL; + use_hotspots.clear(); Resources::instance()->deinit(); } @@ -207,6 +226,8 @@ Common::Error TeenAgentEngine::run() { scene->init(this, _system); inventory->init(this); + + init(); _system->setMouseCursor(res->dseg.ptr(0x00da), 8, 12, 0, 0, 1); @@ -236,7 +257,7 @@ Common::Error TeenAgentEngine::run() { do { _system->showMouse(true); uint32 t0 = _system->getMillis(); - Object *current_object = findObject(scene->getId(), mouse); + Object *current_object = scene->findObject(mouse); while (_event->pollEvent(event)) { if (event.type == Common::EVENT_RTL) { @@ -314,23 +335,6 @@ Common::Error TeenAgentEngine::run() { 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) { if (str.empty()) { return; diff --git a/engines/teenagent/teenagent.h b/engines/teenagent/teenagent.h index 1a12ae0d5f..36bbb815e5 100644 --- a/engines/teenagent/teenagent.h +++ b/engines/teenagent/teenagent.h @@ -53,11 +53,9 @@ public: virtual bool canSaveGameStateCurrently() { return !scene_busy; } virtual bool hasFeature(EngineFeature f) const; - + void init(); void deinit(); - Object *findObject(int id, const Common::Point &point); - void examine(const Common::Point &point, Object *object); void use(Object *object); @@ -111,6 +109,8 @@ private: Audio::AudioStream *_musicStream; Audio::SoundHandle _musicHandle, _soundHandle; const ADGameDescription *_gameDescription; + + Common::Array<Common::Array<UseHotspot> > use_hotspots; }; } // End of namespace TeenAgent |