diff options
| -rw-r--r-- | saga/actor.cpp | 97 | ||||
| -rw-r--r-- | saga/actor.h | 30 | ||||
| -rw-r--r-- | saga/console.cpp | 34 | ||||
| -rw-r--r-- | saga/console.h | 5 | ||||
| -rw-r--r-- | saga/interface.cpp | 2 | ||||
| -rw-r--r-- | saga/interface.h | 6 | ||||
| -rw-r--r-- | saga/render.h | 2 | ||||
| -rw-r--r-- | saga/resnames.h | 2 | ||||
| -rw-r--r-- | saga/saga.cpp | 47 | ||||
| -rw-r--r-- | saga/saga.h | 49 | ||||
| -rw-r--r-- | saga/script.cpp | 159 | ||||
| -rw-r--r-- | saga/script.h | 37 | ||||
| -rw-r--r-- | saga/sfuncs.cpp | 10 | ||||
| -rw-r--r-- | saga/sprite.cpp | 18 | ||||
| -rw-r--r-- | saga/sprite.h | 22 | ||||
| -rw-r--r-- | saga/sthread.cpp | 2 |
16 files changed, 293 insertions, 229 deletions
diff --git a/saga/actor.cpp b/saga/actor.cpp index 34ab300f4d..3436969a75 100644 --- a/saga/actor.cpp +++ b/saga/actor.cpp @@ -130,6 +130,9 @@ int tileDirectionLUT[8][2] = { Actor::Actor(SagaEngine *vm) : _vm(vm) { int i; + int result; + byte *stringsPointer; + size_t stringsLength; ActorData *actor; debug(9, "Actor::Actor()"); @@ -168,10 +171,18 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) { if (_actorContext == NULL) { error("Actor::Actor(): Couldn't load actor module resource context."); } + + result = RSC_LoadResource(_actorContext, RID_ITE_ACTOR_NAMES, &stringsPointer, &stringsLength); // fixme: IHNM + if ((result != SUCCESS) || (stringsLength == 0)) { + error("Error loading strings list resource"); + } + + _vm->loadStrings(_actorsStrings, stringsPointer, stringsLength); + RSC_FreeResource(stringsPointer); for (i = 0; i < ACTORCOUNT; i++) { actor = &_actors[i]; - actor->actorId = ACTOR_INDEX_TO_ID(i); + actor->actorId = actorIndexToId(i); actor->index = i; debug(9, "init actorId=%d index=%d", actor->actorId, actor->index); actor->nameIndex = ActorTable[i].nameIndex; @@ -212,6 +223,7 @@ Actor::~Actor() { free(_newPathNodeList); free(_pathList); free(_pathCell); + _actorsStrings.freeMem(); //release resources for (i = 0; i < ACTORCOUNT; i++) { actor = &_actors[i]; @@ -307,7 +319,7 @@ void Actor::realLocation(ActorLocation &location, uint16 objectId, uint16 walkFl } if (objectId != ID_NOTHING) { - if (IS_VALID_ACTOR_ID(objectId)) { + if (validActorId(objectId)) { actor = getActor(objectId); location.add( actor->location); } else { @@ -340,7 +352,7 @@ void Actor::actorFaceTowardsPoint(uint16 actorId, const ActorLocation &toLocatio void Actor::actorFaceTowardsObject(uint16 actorId, uint16 objectId) { ActorData *actor; - if (IS_VALID_ACTOR_ID(objectId)) { + if (validActorId(objectId)) { actor = getActor(objectId); actorFaceTowardsPoint(actorId, actor->location); } else { @@ -348,10 +360,16 @@ void Actor::actorFaceTowardsObject(uint16 actorId, uint16 objectId) { } } +const char * Actor::getActorName(uint16 actorId) { + ActorData *actor; + actor = getActor(actorId); + return _actorsStrings.getString(actor->nameIndex); +} + ActorData *Actor::getActor(uint16 actorId) { ActorData *actor; - if (!IS_VALID_ACTOR_ID(actorId)) + if (!validActorId(actorId)) error("Actor::getActor Wrong actorId 0x%X", actorId); if (actorId == ID_PROTAG) { @@ -361,7 +379,7 @@ ActorData *Actor::getActor(uint16 actorId) { return _protagonist; } - actor = &_actors[ACTOR_ID_TO_INDEX(actorId)]; + actor = &_actors[actorIdToIndex(actorId)]; if (actor->disabled) error("Actor::getActor disabled actorId 0x%X", actorId); @@ -907,7 +925,7 @@ int Actor::drawActors() { ActorOrderList::iterator actorDrawOrderIterator; ActorData *actor; int frameNumber; - SPRITELIST *spriteList; + SpriteList *spriteList; SURFACE *back_buf; @@ -924,7 +942,7 @@ int Actor::drawActors() { continue; } frameNumber = 8; - spriteList = _vm->_mainSprites; + spriteList = _vm->_sprite->_mainSprites; } else { frameNumber = actor->frameNumber; spriteList = actor->spriteList; @@ -1871,77 +1889,24 @@ void Actor::drawPathTest() { #endif } -/* // Console wrappers - must be safe to run -// TODO - checkup ALL arguments, cause wrong arguments may fall function with "error" - -void Actor::CF_actor_move(int argc, const char **argv) { - uint16 actorId = (uint16) atoi(argv[1]); - Point movePoint; - - movePoint.x = atoi(argv[2]); - movePoint.y = atoi(argv[3]); - - if (!IS_VALID_ACTOR_ID(actorId)) { - _vm->_console->DebugPrintf("Actor::CF_actor_move Invalid actorId 0x%X.\n", actorId); - return; - } - - move(actorId, movePoint); -} -void Actor::CF_actor_moverel(int argc, const char **argv) { +void Actor::cmdActorWalkTo(int argc, const char **argv) { uint16 actorId = (uint16) atoi(argv[1]); + ActorLocation location; Point movePoint; movePoint.x = atoi(argv[2]); movePoint.y = atoi(argv[3]); - if (!IS_VALID_ACTOR_ID(actorId)) { - _vm->_console->DebugPrintf("Actor::CF_actor_moverel Invalid actorId 0x%X.\n", actorId); - return; - } + location.fromScreenPoint(movePoint); - moveRelative(actorId, movePoint); -} - -void Actor::CF_actor_seto(int argc, const char **argv) { - uint16 actorId = (uint16) atoi(argv[1]); - int orient; - - orient = atoi(argv[2]); -//TODO orient check - if (!IS_VALID_ACTOR_ID(actorId)) { - _vm->_console->DebugPrintf("Actor::CF_actor_seto Invalid actorId 0x%X.\n",actorId); + if (!validActorId(actorId)) { + _vm->_console->DebugPrintf("Actor::cmActorWalkTo Invalid actorId 0x%X.\n", actorId); return; } + actorWalkTo(actorId, location); } -void Actor::CF_actor_setact(int argc, const char **argv) { - uint16 actorId = (uint16) atoi(argv[1]); - int action_n = 0; - - action_n = atoi(argv[2]); - - if (!IS_VALID_ACTOR_ID(actorId)) { - _vm->_console->DebugPrintf("Actor::CF_actor_setact Invalid actorId 0x%X.\n",actorId); - return; - } - -//TODO action_n check - if ((action_n < 0) || (action_n >= actor->action_ct)) { - _vm->_console->DebugPrintf("Invalid action number.\n"); - return; - } - - _vm->_console->DebugPrintf("Action frame counts: %d %d %d %d.\n", - actor->act_tbl[action_n].dir[0].frame_count, - actor->act_tbl[action_n].dir[1].frame_count, - actor->act_tbl[action_n].dir[2].frame_count, - actor->act_tbl[action_n].dir[3].frame_count); - - setAction(actorId, action_n, ACTION_LOOP); -} -*/ } // End of namespace Saga diff --git a/saga/actor.h b/saga/actor.h index 0b7a114411..dfb6421b19 100644 --- a/saga/actor.h +++ b/saga/actor.h @@ -29,10 +29,11 @@ #include "saga/sprite.h" #include "saga/actordata.h" #include "saga/list.h" +#include "saga/saga.h" namespace Saga { -//#define ACTOR_DEBUG +#define ACTOR_DEBUG #define ACTOR_BARRIERS_MAX 16 @@ -56,16 +57,6 @@ namespace Saga { #define PATH_NODE_EMPTY -1 - -#define ID_NOTHING 0 -#define ID_PROTAG 1 - -#define IS_VALID_ACTOR_INDEX(index) ((index >= 0) && (index < ACTORCOUNT)) -#define IS_VALID_ACTOR_ID(id) ((id == 1) || (id >= 0x2000) && (id < (0x2000 | ACTORCOUNT))) -#define ACTOR_ID_TO_INDEX(id) ((((uint16)id) == 1 ) ? 0 : (int)(((uint16)id) & ~0x2000)) -#define ACTOR_INDEX_TO_ID(index) ((((int)index) == 0 ) ? 1 : (uint16)(((int)index) | 0x2000)) - - enum ActorActions { kActionWait = 0, kActionWalkToPoint = 1, @@ -207,7 +198,7 @@ struct ActorData { uint8 cycleTimeCount; uint8 cycleFlags; - SPRITELIST *spriteList; // Actor's sprite list data + SpriteList *spriteList; // Actor's sprite list data int spriteListResourceId; // Actor's sprite list resource id ActorFrameSequence *frames; // Actor's frames @@ -275,18 +266,20 @@ public: Actor(SagaEngine *vm); ~Actor(); -/* - void CF_actor_move(int argc, const char **argv); - void CF_actor_moverel(int argc, const char **argv); - void CF_actor_seto(int argc, const char **argv); - void CF_actor_setact(int argc, const char **argv); -*/ + + void cmdActorWalkTo(int argc, const char **argv); + + bool validActorId(uint16 id) { return (id == 1) || ((id >= 0x2000) && (id < (0x2000 | ACTORCOUNT))); } + int actorIdToIndex(uint16 id) { return (id == 1 ) ? 0 : (id & ~0x2000); } + uint16 actorIndexToId(int index) { return (index == 0 ) ? 1 : (index | 0x2000); } + int direct(int msec); int drawActors(); void updateActorsScene(); // calls from scene loading to update Actors info void drawPathTest(); + const char * getActorName(uint16 actorId); bool actorEndWalk(uint16 actorId, bool recurse); bool actorWalkTo(uint16 actorId, const ActorLocation &toLocation); ActorData *getActor(uint16 actorId); @@ -350,6 +343,7 @@ private: ActorOrderList _drawOrderList; ActorData _actors[ACTORCOUNT]; SpeechData _activeSpeech; + StringsList _actorsStrings; //path stuff Rect _barrierList[ACTOR_BARRIERS_MAX]; diff --git a/saga/console.cpp b/saga/console.cpp index 3e5184f5fb..cb5df66190 100644 --- a/saga/console.cpp +++ b/saga/console.cpp @@ -47,10 +47,7 @@ Console::Console(SagaEngine *vm) : Common::Debugger<Console>() { // CVAR_Register_I(&_musicEnabled, "music", NULL, CVAR_CFG, 0, 1); // Actor commands - DCmd_Register("actor_move", &Console::Cmd_ActorMove); - DCmd_Register("actor_moverel", &Console::Cmd_ActorMoveRel); - DCmd_Register("actor_seto", &Console::Cmd_ActorSetO); - DCmd_Register("actor_setact", &Console::Cmd_ActorSetAct); + DCmd_Register("actor_walk_to", &Console::cmdActorWalkTo); // Animation commands DCmd_Register("anim_info", &Console::Cmd_AnimInfo); @@ -135,37 +132,14 @@ bool Console::Cmd_Help(int argc, const char **argv) { return true; } -bool Console::Cmd_ActorMove(int argc, const char **argv) { -/* if (argc != 4) +bool Console::cmdActorWalkTo(int argc, const char **argv) { + if (argc != 4) DebugPrintf("Usage: %s <Actor id> <lx> <ly>\n", argv[0]); else - _vm->_actor->CF_actor_move(argc, argv);*/ + _vm->_actor->cmdActorWalkTo(argc, argv); return true; } -bool Console::Cmd_ActorMoveRel(int argc, const char **argv) { -/* if (argc != 4) - DebugPrintf("Usage: %s <Actor id> <lx> <ly>\n", argv[0]); - else - _vm->_actor->CF_actor_moverel(argc, argv);*/ - return true; -} - -bool Console::Cmd_ActorSetO(int argc, const char **argv) { -/* if (argc != 3) - DebugPrintf("Usage: %s <Actor id> <Orientation>\n", argv[0]); - else - _vm->_actor->CF_actor_seto(argc, argv);*/ - return true; -} - -bool Console::Cmd_ActorSetAct(int argc, const char **argv) { -/* if (argc != 3) - DebugPrintf("Usage: %s <Actor id> <Action #>\n", argv[0]); - else - _vm->_actor->CF_actor_setact(argc, argv);*/ - return true; -} bool Console::Cmd_AnimInfo(int argc, const char **argv) { _vm->_anim->animInfo(); diff --git a/saga/console.h b/saga/console.h index e5ecd8cedf..a32601a1e4 100644 --- a/saga/console.h +++ b/saga/console.h @@ -43,10 +43,7 @@ private: bool Cmd_Exit(int argc, const char **argv); bool Cmd_Help(int argc, const char **argv); - bool Cmd_ActorMove(int argc, const char **argv); - bool Cmd_ActorMoveRel(int argc, const char **argv); - bool Cmd_ActorSetO(int argc, const char **argv); - bool Cmd_ActorSetAct(int argc, const char **argv); + bool cmdActorWalkTo(int argc, const char **argv); bool Cmd_AnimInfo(int argc, const char **argv); diff --git a/saga/interface.cpp b/saga/interface.cpp index 96813e6ad4..05e7afe96e 100644 --- a/saga/interface.cpp +++ b/saga/interface.cpp @@ -758,7 +758,7 @@ void Interface::drawInventory() { drawPoint.x = x + col * width; drawPoint.y = y + row * height; - _vm->_sprite->draw(back_buf, _vm->_mainSprites, + _vm->_sprite->draw(back_buf, _vm->_sprite->_mainSprites, ObjectTable[_inventory[i]].spritelistRn, drawPoint, 256); diff --git a/saga/interface.h b/saga/interface.h index 8939566bf6..28f648c7bf 100644 --- a/saga/interface.h +++ b/saga/interface.h @@ -150,7 +150,7 @@ struct INTERFACE_PANEL { int set_button; int nbuttons; INTERFACE_BUTTON *buttons; - SPRITELIST *sprites; + SpriteList *sprites; }; struct INTERFACE_DESC { @@ -252,8 +252,8 @@ private: char _statusText[STATUS_TEXT_LEN]; int _leftPortrait; int _rightPortrait; - SPRITELIST *_defPortraits; - SPRITELIST *_scenePortraits; + SpriteList *_defPortraits; + SpriteList *_scenePortraits; int _activeVerb; SCRIPT_THREAD *_iThread; diff --git a/saga/render.h b/saga/render.h index c217b09b77..2fca248868 100644 --- a/saga/render.h +++ b/saga/render.h @@ -83,7 +83,7 @@ private: int _tmp_buf_w; int _tmp_buf_h; - SPRITELIST *_test_sprite; + SpriteList *_test_sprite; unsigned int _fps; unsigned int _framecount; diff --git a/saga/resnames.h b/saga/resnames.h index 7d4ee0806a..215a34fd6e 100644 --- a/saga/resnames.h +++ b/saga/resnames.h @@ -55,6 +55,8 @@ namespace Saga { #define RID_ITE_SETUP_PANEL 5 #define RID_ITE_MAIN_SPRITES 6 +#define RID_ITE_MAIN_STRINGS 35 //main strings +#define RID_ITE_ACTOR_NAMES 36 //actors names #define RID_ITE_COMMAND_BUTTONSPRITES 7 #define RID_ITE_DEFAULT_PORTRAITS 125 diff --git a/saga/saga.cpp b/saga/saga.cpp index 590f3e63bc..7f8dd3c946 100644 --- a/saga/saga.cpp +++ b/saga/saga.cpp @@ -219,8 +219,6 @@ int SagaEngine::go() { _previousTicks = _system->getMillis(); - _sprite->loadList(RID_ITE_MAIN_SPRITES, &_mainSprites); - // Begin Main Engine Loop _scene->startScene(); @@ -285,4 +283,49 @@ void SagaEngine::shutdown() { _system->quit(); } +void SagaEngine::loadStrings(StringsList &stringsList, const byte *stringsPointer, size_t stringsLength) { + uint16 stringsCount; + uint16 i; + size_t offset; + + + stringsList.stringsPointer = (byte*)malloc(stringsLength); + memcpy(stringsList.stringsPointer, stringsPointer, stringsLength); + + MemoryReadStreamEndian scriptS(stringsList.stringsPointer, stringsLength, IS_BIG_ENDIAN); + + offset = scriptS.readUint16(); + if (offset > stringsLength) { + error("Invalid string offset"); + } + + stringsCount = offset / 2; + stringsList.stringsCount = stringsCount; + + stringsList.strings = (const char **)malloc(stringsCount * sizeof(const char *)); + if (stringsList.strings == NULL) { + error("No enough memory for strings list"); + } + + scriptS.seek(0); + for (i = 0; i < stringsCount; i++) { + offset = scriptS.readUint16(); + if (offset > stringsLength) { + error("invalid string offset"); + } + stringsList.strings[i] = (const char *)stringsList.stringsPointer + offset; + } +} + +const char *SagaEngine::getObjectName(uint16 objectId) { + + switch (objectIdType(objectId)) { + case kGameObjectActor: + return _actor->getActorName(objectId); + break; + } + //todo: object name & etc + return NULL; +} + } // End of namespace Saga diff --git a/saga/saga.h b/saga/saga.h index a31cfaefc4..7e07cce4c5 100644 --- a/saga/saga.h +++ b/saga/saga.h @@ -39,6 +39,7 @@ #include "saga/text.h" #include "saga/gfx.h" +#include "saga/list.h" namespace Saga { @@ -63,8 +64,13 @@ class PalAnim; #define PBOUNDS(n,max) (((n)>=(0))&&((n)<(max))) #define MAXPATH 512 +#define IS_BIG_ENDIAN ((_vm->_features & GF_BIG_ENDIAN_DATA) != 0) + +#define ID_NOTHING 0 +#define ID_PROTAG 1 + struct RSCFILE_CONTEXT; -struct SPRITELIST; +struct StringList; enum ERRORCODE { MEM = -2, @@ -77,6 +83,14 @@ enum SAGAGameType { GType_IHNM }; +enum GameObjectTypes { + kGameObjectNone = 0, + kGameObjectActor = 1, + kGameObjectObject = 2, + kGameObjectHitZone = 3, + kGameObjectStepZone = 4 +}; + enum scriptTimings { kScriptTimeTicksPerSecond = (728L/10L), kRepeatSpeed = 40, // 25 frames/sec @@ -109,15 +123,33 @@ enum HitZoneFlags { kHitZoneTerminus = (1 << 3) }; +struct StringsList { + byte *stringsPointer; + int stringsCount; + const char **strings; + + const char *getString(int index) const { + if (stringsCount <= index) + error("StringList::getString wrong index 0x%X", index); + return strings[index]; + } + + void freeMem() { + free(strings); + free(stringsPointer); + memset(this, 0, sizeof(*this)); + } + + StringsList() { + memset(this, 0, sizeof(*this)); + } +}; + struct CLICKAREA { int n_points; Point *points; }; - -#define IS_BIG_ENDIAN ((_vm->_features & GF_BIG_ENDIAN_DATA) != 0) - - enum GAME_IDS { // Dreamers Guild GID_ITE_DEMO_G = 0, @@ -236,6 +268,10 @@ inline int integerCompare(int i1, int i2) { return ((i1) > (i2) ? 1 : ((i1) < (i2) ? -1 : 0)); } +inline int objectIdType(uint16 objectId) { + return objectId >> 13; +} + class SagaEngine : public Engine { void errorString(const char *buf_input, char *buf_output); @@ -273,7 +309,6 @@ public: Events *_events; PalAnim *_palanim; - SPRITELIST *_mainSprites; /** Random number generator */ Common::RandomSource _rnd; @@ -288,6 +323,8 @@ public: int decodeBGImage(const byte *image_data, size_t image_size, byte **output_buf, size_t *output_buf_len, int *w, int *h); const byte *getImagePal(const byte *image_data, size_t image_size); + void loadStrings(StringsList &stringsList, const byte *stringsPointer, size_t stringsLength); + const char *getObjectName(uint16 objectId); public: TEXTLIST *textCreateList(); diff --git a/saga/script.cpp b/saga/script.cpp index 8482bc6880..b68c19d95b 100644 --- a/saga/script.cpp +++ b/saga/script.cpp @@ -30,6 +30,7 @@ #include "saga/script.h" #include "saga/stream.h" +#include "saga/interface.h" namespace Saga { @@ -38,11 +39,14 @@ namespace Saga { Script::Script() { GAME_RESOURCEDESC gr_desc; RSCFILE_CONTEXT *s_lut_ctxt; + RSCFILE_CONTEXT *resourceContext; byte *rsc_ptr; size_t rsc_len; int prevTell; int result; int i, j; + byte *stringsPointer; + size_t stringsLength; //initialize member variables _dbg_thread = 0; @@ -54,6 +58,11 @@ Script::Script() { _abortEnabled = true; _skipSpeeches = false; + _currentVerb = kVerbNone; + _stickyVerb = kVerbWalkTo; + _leftButtonVerb = kVerbNone; + _rightButtonVerb = kVerbNone; + _dataBuf[0].data = _dataBuf[1].data = (ScriptDataWord *)calloc(SCRIPT_DATABUF_LEN, sizeof(ScriptDataWord));; _dataBuf[0].length = _dataBuf[1].length = SCRIPT_DATABUF_LEN; @@ -131,6 +140,16 @@ Script::Script() { setupScriptFuncList(); + resourceContext = _vm->getFileContext(GAME_RESOURCEFILE, 0); + + result = RSC_LoadResource(resourceContext, RID_ITE_MAIN_STRINGS, &stringsPointer, &stringsLength); // fixme: IHNM + if ((result != SUCCESS) || (stringsLength == 0)) { + error("Error loading strings list resource"); + } + + _vm->loadStrings(_mainStrings, stringsPointer, stringsLength); + RSC_FreeResource(stringsPointer); + _initialized = true; } @@ -142,6 +161,8 @@ Script::~Script() { } debug(0, "Shutting down scripting subsystem."); + + _mainStrings.freeMem(); // Free script lookup table free(_scriptLUT); @@ -238,7 +259,7 @@ int Script::getBit(int bufNumber, ScriptDataWord bitNumber, int *bitState) { // Loads a script; including script bytecode and dialogue list int Script::loadScript(int script_num) { - SCRIPTDATA *script_data; + ScriptData *script_data; byte *bytecode_p; size_t bytecode_len; uint32 scriptl_rn; @@ -266,15 +287,14 @@ int Script::loadScript(int script_num) { // Initialize script data structure debug(0, "Loading script data for script #%d", script_num); - script_data = (SCRIPTDATA *)malloc(sizeof(*script_data)); + script_data = (ScriptData *)malloc(sizeof(*script_data)); if (script_data == NULL) { error("Memory allocation failed"); } script_data->loaded = 0; - // Initialize script pointers - script_data->strings = NULL; + // Initialize script pointers script_data->bytecode = NULL; script_data->voice = NULL; @@ -304,8 +324,9 @@ int Script::loadScript(int script_num) { } // Convert strings list resource to logical strings list - loadStrings(stringsPointer, stringsLength, script_data->strings); - + _vm->loadStrings(script_data->strings, stringsPointer, stringsLength); + RSC_FreeResource(stringsPointer); + // Load voice resource lookup table if (_voiceLUTPresent) { voicelut_rn = _scriptLUT[script_num].voice_lut_rn; @@ -343,10 +364,7 @@ int Script::freeScript() { debug(0, "Releasing script data."); // Finish initialization - if (_currentScript->strings != NULL) { - free(_currentScript->strings->strings); - } - free(_currentScript->strings); + _currentScript->strings.freeMem(); if (_currentScript->bytecode != NULL) { free(_currentScript->bytecode->entrypoints); @@ -446,59 +464,10 @@ SCRIPT_BYTECODE *Script::loadBytecode(byte *bytecode_p, size_t bytecode_len) { return bc_new_data; } -const char *Script::getString(int index) { - if (_currentScript->strings->stringsCount <= index) - error("Script::getString wrong index 0x%X", index); - return _currentScript->strings->strings[index]; -} - -// Reads a logical strings list from a strings list resource in memory. -// Returns NULL on failure. -void Script::loadStrings(const byte *stringsPointer, size_t stringsLength, StringsList *&strings) { - uint16 stringsCount; - uint16 i; - size_t offset; - - debug(9, "Loading strings list..."); - - // Allocate dialogue list structure - strings = (StringsList *)malloc(sizeof(*strings)); - if (strings == NULL) { - error("No enough memory for strings list"); - } - - MemoryReadStreamEndian scriptS(stringsPointer, stringsLength, IS_BIG_ENDIAN); - - // First uint16 is the offset of the first string - offset = scriptS.readUint16(); - if (offset > stringsLength) { - error("Invalid string offset"); - } - - // Calculate table length - stringsCount = offset / 2; - strings->stringsCount = stringsCount; - - // Allocate table of string pointers - strings->strings = (const char **)malloc(stringsCount * sizeof(const char *)); - if (strings->strings == NULL) { - error("No enough memory for strings list"); - } - - // Read in tables from dialogue list resource - scriptS.seek(0); - for (i = 0; i < stringsCount; i++) { - offset = scriptS.readUint16(); - if (offset > stringsLength) { - error("invalid string offset"); - } - strings->strings[i] = (const char *)stringsPointer + offset; - } -} // Reads a logical voice LUT from a voice LUT resource in memory. // Returns NULL on failure. -VOICE_LUT *Script::loadVoiceLUT(const byte *voicelut_p, size_t voicelut_len, SCRIPTDATA *script) { +VOICE_LUT *Script::loadVoiceLUT(const byte *voicelut_p, size_t voicelut_len, ScriptData *script) { VOICE_LUT *voice_lut; uint16 i; @@ -509,7 +478,7 @@ VOICE_LUT *Script::loadVoiceLUT(const byte *voicelut_p, size_t voicelut_len, SCR } voice_lut->n_voices = voicelut_len / 2; - if (voice_lut->n_voices != script->strings->stringsCount) { + if (voice_lut->n_voices != script->strings.stringsCount) { warning("Error: Voice LUT entries do not match dialogue entries"); return NULL; } @@ -588,6 +557,74 @@ void Script::scriptExec(int argc, const char **argv) { SThreadExecute(_dbg_thread, ep_num); } +// verb +void Script::showVerb() { + const char *verbName; + const char *object1Name; + const char *object2Name; + char statusString[STATUS_TEXT_LEN]; + + + if (_leftButtonVerb == kVerbNone) { + _vm->_interface->setStatusText(""); + return; + } + + verbName = _mainStrings.getString(_leftButtonVerb - 1); + + if (objectIdType(_currentObject[0]) == kGameObjectNone) { + _vm->_interface->setStatusText(verbName); + return; + } + + object1Name = _vm->getObjectName(_currentObject[0]); + + if (!_secondObjectNeeded) { + snprintf(statusString, STATUS_TEXT_LEN, "%s %s", verbName, object1Name); + _vm->_interface->setStatusText(statusString); + return; + } + + + if (objectIdType(_currentObject[1]) != kGameObjectNone) { + object2Name = _vm->getObjectName(_currentObject[1]); + } else { + object2Name = ""; + } + + if (_leftButtonVerb == kVerbGive) { + snprintf(statusString, STATUS_TEXT_LEN, "Give %s to %s", object1Name, object2Name); + _vm->_interface->setStatusText(statusString); + } else { + if (_leftButtonVerb == kVerbUse) { + snprintf(statusString, STATUS_TEXT_LEN, "Use %s with %s", object1Name, object2Name); + _vm->_interface->setStatusText(statusString); + } else { + snprintf(statusString, STATUS_TEXT_LEN, "%s %s", verbName, object1Name); + _vm->_interface->setStatusText(statusString); + } + } +} + +void Script::setVerb(int verb) { + _pendingObject[0] = ID_NOTHING; + _currentObject[0] = ID_NOTHING; + _pendingObject[1] = ID_NOTHING; + _currentObject[1] = ID_NOTHING; + _firstObjectSet = false; + _secondObjectNeeded = false; + + setLeftButtonVerb( verb ); + showVerb(); +} + +void Script::setLeftButtonVerb(int verb) { +} + +void Script::doVerb() { +} + +// console wrappers void Script::CF_script_togglestep() { _dbg_singlestep = !_dbg_singlestep; } diff --git a/saga/script.h b/saga/script.h index cbc1c3c3d2..662efd70e7 100644 --- a/saga/script.h +++ b/saga/script.h @@ -199,20 +199,15 @@ struct SCRIPT_BYTECODE { PROC_TBLENTRY *entrypoints; }; -struct StringsList { - int stringsCount; - const char **strings; -}; - struct VOICE_LUT { int n_voices; int *voices; }; -struct SCRIPTDATA { +struct ScriptData { int loaded; SCRIPT_BYTECODE *bytecode; - StringsList *strings; + StringsList strings; VOICE_LUT *voice; }; @@ -239,19 +234,23 @@ public: int loadScript(int scriptNum); int freeScript(); SCRIPT_BYTECODE *loadBytecode(byte *bytecode_p, size_t bytecode_len); - void loadStrings(const byte *stringsList, size_t stringsLength, StringsList *&strings); - VOICE_LUT *loadVoiceLUT(const byte *voicelut_p, size_t voicelut_len, SCRIPTDATA *script); + VOICE_LUT *loadVoiceLUT(const byte *voicelut_p, size_t voicelut_len, ScriptData *script); int disassemble(SCRIPT_BYTECODE *script_list, StringsList *strings); bool isInitialized() const { return _initialized; } bool isVoiceLUTPresent() const { return _voiceLUTPresent; } - SCRIPTDATA *currentScript() { return _currentScript; } + ScriptData *currentScript() { return _currentScript; } ScriptDataBuf *dataBuffer(int idx) { return &_dataBuf[idx]; } int getWord(int bufNumber, int wordNumber, ScriptDataWord *data); int putWord(int bufNumber, int wordNumber, ScriptDataWord data); int setBit(int bufNumber, ScriptDataWord bitNumber, int bitState); int getBit(int bufNumber, ScriptDataWord bitNumber, int *bitState); - const char *getString(int index); + const char * getScriptString(int index) const { return _currentScript->strings.getString(index); } + + void doVerb(); + void showVerb(); + void setVerb(int verb); + void setLeftButtonVerb(int verb); void scriptInfo(); void scriptExec(int argc, const char **argv); @@ -263,10 +262,22 @@ protected: SCRIPT_LUT_ENTRY *_scriptLUT; int _scriptLUTMax; uint16 _scriptLUTEntryLen; - SCRIPTDATA *_currentScript; + ScriptData *_currentScript; ScriptDataBuf _dataBuf[SCRIPT_DATABUF_NUM]; ScriptThreadList _threadList; - + StringsList _mainStrings; + +//verb + bool _firstObjectSet; + bool _secondObjectNeeded; + uint16 _currentObject[2]; + uint16 _pendingObject[2]; + int _currentVerb; + int _stickyVerb; + int _leftButtonVerb; + int _rightButtonVerb; + int _pendingVerb; + public: bool _skipSpeeches; diff --git a/saga/sfuncs.cpp b/saga/sfuncs.cpp index 4b8c340154..eb2e3c9c30 100644 --- a/saga/sfuncs.cpp +++ b/saga/sfuncs.cpp @@ -135,7 +135,7 @@ void Script::setupScriptFuncList(void) { int Script::SF_putString(SCRIPTFUNC_PARAMS) { ScriptDataWord param = thread->pop(); - _vm->_console->DebugPrintf(getString(param)); + _vm->_console->DebugPrintf(getScriptString(param)); return SUCCESS; } @@ -189,7 +189,7 @@ int Script::SF_objectIsCarried(SCRIPTFUNC_PARAMS) { int Script::sfStatusBar(SCRIPTFUNC_PARAMS) { ScriptDataWord param = thread->pop(); - return _vm->_interface->setStatusText(getString(param)); + return _vm->_interface->setStatusText(getScriptString(param)); } // Script function #5 (0x05) @@ -352,7 +352,7 @@ int Script::sfSetFollower(SCRIPTFUNC_PARAMS) { actorId = getSWord(thread->pop()); targetObject = getSWord(thread->pop()); - debug(1, "sfSetFollower(%d, %d) [%d]", actorId, targetObject, ACTOR_ID_TO_INDEX(actorId)); + debug(1, "sfSetFollower(%d, %d) [%d]", actorId, targetObject, _vm->_actor->actorIdToIndex(actorId)); actor = _vm->_actor->getActor(actorId); actor->targetObject = targetObject; @@ -738,7 +738,7 @@ int Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) { for (i = 0; i < actorsCount; i++) actorsIds[i] = getSWord(thread->pop()); - string = getString(stringId); + string = getScriptString(stringId); _vm->_actor->simulSpeech(string, actorsIds, actorsCount, 0); return SUCCESS; @@ -1080,7 +1080,7 @@ int Script::sfPlacard(SCRIPTFUNC_PARAMS) { text_entry.text_y = (disp.scene_h - _vm->_font->getHeight(MEDIUM_FONT_ID)) / 2; text_entry.font_id = MEDIUM_FONT_ID; text_entry.flags = FONT_OUTLINE | FONT_CENTERED; - text_entry.string = getString(stringId); + text_entry.string = getScriptString(stringId); placardTextEntry = _vm->textAddEntry(scene_info.text_list, &text_entry); diff --git a/saga/sprite.cpp b/saga/sprite.cpp index 0f0a335bde..940ea56a62 100644 --- a/saga/sprite.cpp +++ b/saga/sprite.cpp @@ -52,6 +52,8 @@ Sprite::Sprite(SagaEngine *vm) : _vm(vm), _initialized(false) { return; } + loadList(RID_ITE_MAIN_SPRITES, &_mainSprites); //fixme: IHNM may have no such list + _initialized = true; } @@ -65,8 +67,8 @@ Sprite::~Sprite(void) { free(_decodeBuf); } -int Sprite::loadList(int resource_num, SPRITELIST **sprite_list_p) { - SPRITELIST *new_slist; +int Sprite::loadList(int resource_num, SpriteList **sprite_list_p) { + SpriteList *new_slist; byte *spritelist_data; size_t spritelist_len; uint16 sprite_count; @@ -83,7 +85,7 @@ int Sprite::loadList(int resource_num, SPRITELIST **sprite_list_p) { sprite_count = readS.readUint16(); - new_slist = (SPRITELIST *)malloc(sizeof(*new_slist)); + new_slist = (SpriteList *)malloc(sizeof(*new_slist)); if (new_slist == NULL) { return MEM; } @@ -113,7 +115,7 @@ int Sprite::loadList(int resource_num, SPRITELIST **sprite_list_p) { return SUCCESS; } -int Sprite::appendList(int resource_num, SPRITELIST *spritelist) { +int Sprite::appendList(int resource_num, SpriteList *spritelist) { byte *spritelist_data; size_t spritelist_len; void *test_p; @@ -157,11 +159,11 @@ int Sprite::appendList(int resource_num, SPRITELIST *spritelist) { return SUCCESS; } -int Sprite::getListLen(SPRITELIST *spritelist) { +int Sprite::getListLen(SpriteList *spritelist) { return spritelist->sprite_count; } -int Sprite::freeSprite(SPRITELIST *spritelist) { +int Sprite::freeSprite(SpriteList *spritelist) { int i; for (i = 0; i <= spritelist->append_count; i++) { @@ -175,7 +177,7 @@ int Sprite::freeSprite(SPRITELIST *spritelist) { return SUCCESS; } -int Sprite::draw(SURFACE *ds, SPRITELIST *sprite_list, int sprite_num, const Point &screenCoord, int scale) { +int Sprite::draw(SURFACE *ds, SpriteList *sprite_list, int sprite_num, const Point &screenCoord, int scale) { int offset; int offset_idx; byte *sprite_p; @@ -266,7 +268,7 @@ int Sprite::draw(SURFACE *ds, SPRITELIST *sprite_list, int sprite_num, const Poi return SUCCESS; } -int Sprite::drawOccluded(SURFACE *ds, SPRITELIST *sprite_list, int sprite_num, const Point &screenCoord, int scale, int depth) { +int Sprite::drawOccluded(SURFACE *ds, SpriteList *sprite_list, int sprite_num, const Point &screenCoord, int scale, int depth) { int offset; int offset_idx; byte *sprite_p; diff --git a/saga/sprite.h b/saga/sprite.h index be64c0a83d..c1590db8a1 100644 --- a/saga/sprite.h +++ b/saga/sprite.h @@ -48,7 +48,7 @@ struct SPRITELIST_OFFSET { uint32 offset; }; -struct SPRITELIST { +struct SpriteList { int append_count; int sprite_count; SPRITELIST_OFFSET *offset_list; @@ -58,17 +58,19 @@ struct SPRITELIST { class Sprite { - public: +public: + SpriteList *_mainSprites; + Sprite(SagaEngine *vm); ~Sprite(void); - int loadList(int resource_num, SPRITELIST **sprite_list_p); - int appendList(int resource_num, SPRITELIST *spritelist); - int getListLen(SPRITELIST *spritelist); - int freeSprite(SPRITELIST *spritelist); - int draw(SURFACE *ds, SPRITELIST *sprite_list, int sprite_num, const Point &screenCoord, int scale); - int drawOccluded(SURFACE *ds, SPRITELIST *sprite_list, int sprite_num, const Point &screenCoord, int scale, int depth); - - private: + int loadList(int resource_num, SpriteList **sprite_list_p); + int appendList(int resource_num, SpriteList *spritelist); + int getListLen(SpriteList *spritelist); + int freeSprite(SpriteList *spritelist); + int draw(SURFACE *ds, SpriteList *sprite_list, int sprite_num, const Point &screenCoord, int scale); + int drawOccluded(SURFACE *ds, SpriteList *sprite_list, int sprite_num, const Point &screenCoord, int scale, int depth); + +private: int decodeRLESprite(const byte *inbuf, size_t inbuf_len, byte *outbuf, size_t outbuf_len); void scaleSprite(byte *buf, int width, int height, int scale); void scaleSpriteCoords(int scale, int *width, int *height, int *x_align, int *y_align); diff --git a/saga/sthread.cpp b/saga/sthread.cpp index 028354fc77..fa9530cd4c 100644 --- a/saga/sthread.cpp +++ b/saga/sthread.cpp @@ -754,7 +754,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) { data = first = thread->stackTop(); for (i = 0; i < stringsCount; i++) { data = thread->pop(); - strings[i] = getString(data); + strings[i] = getScriptString(data); } // now data contains last string index |
