From 502b279d243d79f46bb8a151ae610949d30bf757 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Wed, 15 Dec 2004 00:24:12 +0000 Subject: Patch #1081904 ITE: MAC demo support o Endianness-aware resource loading o Removed ys_dl_list in favor of our object implementation o Cleanup in actor code o Partial support for ITE Mac rereleased demo svn-id: r16051 --- saga/actionmap.cpp | 16 +-- saga/actor.cpp | 318 +++++++++++++++++++++--------------------------- saga/actor.h | 123 +++++++++++++++---- saga/animation.cpp | 162 ++++++++++++++---------- saga/animation.h | 13 +- saga/events.cpp | 68 ++++------- saga/events.h | 7 +- saga/font.cpp | 29 ++--- saga/game.cpp | 64 ++++++++-- saga/game.h | 4 +- saga/game_mod.h | 15 ++- saga/ihnm_introproc.cpp | 1 - saga/image.cpp | 11 +- saga/isomap.cpp | 29 ++--- saga/ite_introproc.cpp | 2 +- saga/list.h | 154 +++++++++++++++++++++++ saga/music.cpp | 21 +++- saga/objectmap.cpp | 20 +-- saga/palanim.cpp | 9 +- saga/resnames.h | 2 + saga/rscfile.cpp | 32 +++-- saga/rscfile_mod.h | 1 + saga/saga.h | 1 - saga/scene.cpp | 120 ++++++++---------- saga/scene.h | 11 +- saga/script.cpp | 47 +++---- saga/script.h | 10 +- saga/sdebug.cpp | 24 ++-- saga/sndres.cpp | 23 ++-- saga/sprite.cpp | 20 +-- saga/sthread.cpp | 67 ++++------ saga/stream.h | 56 +++++++++ saga/text.cpp | 49 ++------ saga/text.h | 10 +- saga/ys_dl_list.cpp | 239 ------------------------------------ saga/yslib.h | 90 -------------- 36 files changed, 921 insertions(+), 947 deletions(-) create mode 100644 saga/list.h create mode 100644 saga/stream.h delete mode 100644 saga/ys_dl_list.cpp delete mode 100644 saga/yslib.h (limited to 'saga') diff --git a/saga/actionmap.cpp b/saga/actionmap.cpp index e6d467dce9..e3d988c3a0 100644 --- a/saga/actionmap.cpp +++ b/saga/actionmap.cpp @@ -28,6 +28,8 @@ #include "saga/console.h" #include "saga/actionmap.h" +#include "saga/game_mod.h" +#include "saga/stream.h" namespace Saga { @@ -39,10 +41,10 @@ ActionMap::ActionMap(SagaEngine *vm, const byte * exmap_res, size_t exmap_res_le assert(exmap_res != NULL); - MemoryReadStream readS(exmap_res, exmap_res_len); + MemoryReadStreamEndian readS(exmap_res, exmap_res_len, IS_BIG_ENDIAN); // Load exits - _nExits = readS.readSint16LE(); + _nExits = readS.readSint16(); if (_nExits < 0) { return; } @@ -59,8 +61,8 @@ ActionMap::ActionMap(SagaEngine *vm, const byte * exmap_res, size_t exmap_res_le exmap_entry->nClickareas = readS.readByte(); exmap_entry->defaultVerb = readS.readByte(); readS.readByte(); - exmap_entry->exitScene = readS.readUint16LE(); - exmap_entry->entranceNum = readS.readUint16LE(); + exmap_entry->exitScene = readS.readUint16(); + exmap_entry->entranceNum = readS.readUint16(); exmap_entry->clickareas = (CLICKAREA *)malloc(exmap_entry->nClickareas * sizeof *(exmap_entry->clickareas)); @@ -72,7 +74,7 @@ ActionMap::ActionMap(SagaEngine *vm, const byte * exmap_res, size_t exmap_res_le // Load all clickareas for this object for (int k = 0; k < exmap_entry->nClickareas; k++) { clickarea = &exmap_entry->clickareas[k]; - clickarea->n_points = readS.readUint16LE(); + clickarea->n_points = readS.readUint16(); assert(clickarea->n_points != 0); clickarea->points = (Point *)malloc(clickarea->n_points * sizeof *(clickarea->points)); @@ -84,8 +86,8 @@ ActionMap::ActionMap(SagaEngine *vm, const byte * exmap_res, size_t exmap_res_le // Load all points for this clickarea for (int m = 0; m < clickarea->n_points; m++) { point = &clickarea->points[m]; - point->x = readS.readSint16LE(); - point->y = readS.readSint16LE(); + point->x = readS.readSint16(); + point->y = readS.readSint16(); } } } diff --git a/saga/actor.cpp b/saga/actor.cpp index 4e1d9e2d63..860f011be6 100644 --- a/saga/actor.cpp +++ b/saga/actor.cpp @@ -22,7 +22,6 @@ */ #include "saga/saga.h" -#include "saga/yslib.h" #include "saga/gfx.h" #include "saga/game_mod.h" @@ -39,10 +38,20 @@ #include "saga/actor.h" #include "saga/actordata.h" +#include "saga/stream.h" namespace Saga { -static int zCompare(const void *elem1, const void *elem2); +static int actorCompare(const ACTOR& actor1, const ACTOR& actor2) { + if (actor1.a_pt.y == actor2.a_pt.y) { + return 0; + } else if (actor1.a_pt.y < actor2.a_pt.y) { + return -1; + } else { + return 1; + } +} +static ActorList::iterator zeroActorIterator; ACTIONTIMES ActionTDeltas[] = { { ACTION_IDLE, 80 }, @@ -59,33 +68,12 @@ Actor::Actor(SagaEngine *vm) : _vm(vm), _initialized(false) { error("Actor::Actor(): Couldn't load actor module resource context."); } - // Create actor lookup table - _tbl = (YS_DL_NODE **)malloc(ACTORCOUNT * sizeof(*_tbl)); - if (_tbl == NULL) { - error("Actor::Actor(): Memory allocation error."); - return; - } - - for (i = 0; i < ACTORCOUNT; i++) { - _tbl[i] = NULL; - } - - // Create actor alias table - _aliasTbl = (int *)malloc(ACTORCOUNT * sizeof(*_aliasTbl)); - if (_aliasTbl == NULL) { - free(_tbl); - error("Actor::Actor(): Memory allocation error."); - return; - } // Initialize alias table so each index contains itself for (i = 0; i < ACTORCOUNT; i++) { _aliasTbl[i] = i; } - // Create actor list - _list = ys_dll_create(); - _count = 0; _initialized = true; } @@ -94,29 +82,26 @@ Actor::~Actor() { if (!_initialized) { return; } - - if (_tbl) { - free(_tbl); - } } int Actor::direct(int msec) { - YS_DL_NODE *walk_p; + ActorList::iterator actorIterator; ACTOR *actor; - YS_DL_NODE *a_inode; + ActorIntentList::iterator actorIntentIterator; ACTORINTENT *a_intent; int o_idx; int action_tdelta; // Walk down the actor list and direct each actor - for (walk_p = ys_dll_head(_list); walk_p != NULL; walk_p = ys_dll_next(walk_p)) { - actor = (ACTOR *)ys_dll_get_data(walk_p); + for (actorIterator = _list.begin(); actorIterator != _list.end(); ++actorIterator) { + actor = actorIterator.operator->(); + // Process the actor intent list - a_inode = ys_dll_head(actor->a_intentlist); - if (a_inode != NULL) { - a_intent = (ACTORINTENT *)ys_dll_get_data(a_inode); + actorIntentIterator = actor->a_intentlist.begin(); + if (actorIntentIterator != actor->a_intentlist.end()) { + a_intent = actorIntentIterator.operator->(); switch (a_intent->a_itype) { case INTENT_NONE: // Actor doesn't really feel like doing anything at all @@ -144,8 +129,8 @@ int Actor::direct(int msec) { // If this actor intent was flagged as completed, remove it. if (a_intent->a_idone) { - free(a_intent->a_data); - ys_dll_delete(a_inode); + a_intent->deleteData(); + actor->a_intentlist.erase(actorIntentIterator); actor->action = actor->def_action; actor->action_flags = actor->def_action_flags; actor->action_frame = 0; @@ -183,14 +168,14 @@ int Actor::direct(int msec) { } int Actor::drawList() { - YS_DL_NODE *walk_p; + ActorList::iterator actorIterator; ACTOR *actor; - YS_DL_NODE *a_inode; + ActorIntentList::iterator actorIntentIterator; ACTORINTENT *a_intent; SPEAKINTENT *a_speakint; - YS_DL_NODE *a_dnode; + ActorDialogList::iterator actorDialogIterator; ACTORDIALOGUE *a_dialogue; int o_idx; //Orientation index @@ -202,8 +187,8 @@ int Actor::drawList() { back_buf = _vm->_gfx->getBackBuffer(); - for (walk_p = ys_dll_head(_list); walk_p != NULL; walk_p = ys_dll_next(walk_p)) { - actor = (ACTOR *)ys_dll_get_data(walk_p); + for (actorIterator = _list.begin(); actorIterator != _list.end(); ++actorIterator) { + actor = actorIterator.operator->(); o_idx = ActorOrientationLUT[actor->orient]; sprite_num = actor->act_tbl[actor->action].dir[o_idx].frame_index; sprite_num += actor->action_frame; @@ -211,14 +196,14 @@ int Actor::drawList() { // If actor's current intent is to speak, oblige him by // displaying his dialogue - a_inode = ys_dll_head(actor->a_intentlist); - if (a_inode != NULL) { - a_intent = (ACTORINTENT *)ys_dll_get_data(a_inode); + actorIntentIterator = actor->a_intentlist.begin(); + if (actorIntentIterator != actor->a_intentlist.end()) { + a_intent = actorIntentIterator.operator->(); if (a_intent->a_itype == INTENT_SPEAK) { a_speakint = (SPEAKINTENT *)a_intent->a_data; - a_dnode = ys_dll_head(a_speakint->si_diaglist); - if (a_dnode != NULL) { - a_dialogue = (ACTORDIALOGUE *)ys_dll_get_data(a_dnode); + actorDialogIterator = a_speakint->si_diaglist.begin(); + if (actorDialogIterator != a_speakint->si_diaglist.end()) { + a_dialogue = actorDialogIterator.operator->(); diag_x = actor->s_pt.x; diag_y = actor->s_pt.y; diag_y -= ACTOR_DIALOGUE_HEIGHT; @@ -237,37 +222,37 @@ int Actor::drawList() { // dialogue entry if there is a current speak intent present. int Actor::skipDialogue() { - YS_DL_NODE *walk_p; + ActorList::iterator actorIterator; ACTOR *actor; - YS_DL_NODE *a_inode; + ActorIntentList::iterator actorIntentIterator; ACTORINTENT *a_intent; SPEAKINTENT *a_speakint; - YS_DL_NODE *a_dnode; + ActorDialogList::iterator actorDialogIterator; ACTORDIALOGUE *a_dialogue; if (!_initialized) { return FAILURE; } - for (walk_p = ys_dll_head(_list); walk_p != NULL; walk_p = ys_dll_next(walk_p)) { - actor = (ACTOR *)ys_dll_get_data(walk_p); + for (actorIterator = _list.begin(); actorIterator != _list.end(); ++actorIterator) { + actor = actorIterator.operator->(); // Check the actor's current intent for a speak intent - a_inode = ys_dll_head(actor->a_intentlist); - if (a_inode != NULL) { - a_intent = (ACTORINTENT *)ys_dll_get_data(a_inode); + actorIntentIterator = actor->a_intentlist.begin(); + if (actorIntentIterator != actor->a_intentlist.end()) { + a_intent = actorIntentIterator.operator->(); if (a_intent->a_itype == INTENT_SPEAK) { // Okay, found a speak intent. Remove one dialogue entry // from it, releasing any semaphore */ a_speakint = (SPEAKINTENT *)a_intent->a_data; - a_dnode = ys_dll_head(a_speakint->si_diaglist); - if (a_dnode != NULL) { - a_dialogue = (ACTORDIALOGUE *)ys_dll_get_data(a_dnode); + actorDialogIterator = a_speakint->si_diaglist.begin(); + if (actorDialogIterator != a_speakint->si_diaglist.end()) { + a_dialogue = actorDialogIterator.operator->(); if (a_dialogue->d_sem != NULL) { _vm->_script->SThreadReleaseSem(a_dialogue->d_sem); } - ys_dll_delete(a_dnode); + a_speakint->si_diaglist.erase(actorDialogIterator); // And stop any currently playing voices _vm->_sound->stopVoice(); } @@ -300,7 +285,7 @@ int Actor::create(int actor_id, int x, int y) { } int Actor::addActor(ACTOR * actor) { - YS_DL_NODE *new_node; + ActorList::iterator actorIterator; int last_frame; int i; @@ -312,7 +297,7 @@ int Actor::addActor(ACTOR * actor) { return FAILURE; } - if (_tbl[actor->id] != NULL) { + if (_tbl[actor->id] != zeroActorIterator) { return FAILURE; } @@ -340,7 +325,6 @@ int Actor::addActor(ACTOR * actor) { actor->flags = ActorTable[i].flags; actor->a_dcolor = ActorTable[i].color; actor->orient = ACTOR_DEFAULT_ORIENT; - actor->a_intentlist = ys_dll_create(); actor->def_action = 0; actor->def_action_flags = 0; actor->action = 0; @@ -348,35 +332,34 @@ int Actor::addActor(ACTOR * actor) { actor->action_time = 0; actor->action_frame = 0; - new_node = ys_dll_insert(_list, actor, sizeof(*actor), zCompare); - - if (new_node == NULL) { - return FAILURE; - } + actorIterator = _list.pushBack(*actor, actorCompare); - actor = (ACTOR *)ys_dll_get_data(new_node); - actor->node = new_node; + actor = actorIterator.operator->(); - _tbl[i] = new_node; + _tbl[i] = actorIterator; _count++; return SUCCESS; } int Actor::getActorIndex(uint16 actor_id) { - uint16 actor_idx; + uint16 actorIdx; if (actor_id == 1) { - actor_idx = 0; + actorIdx = 0; } else { - actor_idx = actor_id & ~0x2000; + actorIdx = actor_id & ~0x2000; } - if (_tbl[actor_idx] == NULL) { + if (actorIdx >= ACTORCOUNT) { + error("Wrong actorIdx=%i", actorIdx); + } + + if (_tbl[actorIdx] == zeroActorIterator) { return -1; } - return actor_idx; + return actorIdx; } int Actor::actorExists(uint16 actor_id) { @@ -388,7 +371,7 @@ int Actor::actorExists(uint16 actor_id) { actor_idx = actor_id & ~0x2000; } - if (_tbl[actor_idx] == NULL) { + if (_tbl[actor_idx] == zeroActorIterator) { return 0; } @@ -396,9 +379,9 @@ int Actor::actorExists(uint16 actor_id) { } int Actor::speak(int index, const char *d_string, uint16 d_voice_rn, SEMAPHORE *sem) { - YS_DL_NODE *node; + ActorList::iterator actorIterator; ACTOR *actor; - YS_DL_NODE *a_inode; + ActorIntentList::iterator actorIntentIterator; ACTORINTENT *a_intent_p = NULL; SPEAKINTENT *a_speakint; ACTORINTENT a_intent; @@ -411,20 +394,21 @@ int Actor::speak(int index, const char *d_string, uint16 d_voice_rn, SEMAPHORE * a_dialogue.d_sem_held = 1; a_dialogue.d_sem = sem; - node = _tbl[index]; - if (node == NULL) { + actorIterator = _tbl[index]; + if (actorIterator == zeroActorIterator) { return FAILURE; } - actor = (ACTOR *)ys_dll_get_data(node); + actor = actorIterator.operator->(); // If actor's last registered intent is to speak, we can queue the // requested dialogue on that intent context; so examine the last // intent - a_inode = ys_dll_tail(actor->a_intentlist); - if (a_inode != NULL) { - a_intent_p = (ACTORINTENT *)ys_dll_get_data(a_inode); + actorIntentIterator = actor->a_intentlist.end(); + --actorIntentIterator; + if (actorIntentIterator != actor->a_intentlist.end()) { + a_intent_p = actorIntentIterator.operator->(); if (a_intent_p->a_itype == INTENT_SPEAK) { use_existing_ai = 1; } @@ -433,25 +417,19 @@ int Actor::speak(int index, const char *d_string, uint16 d_voice_rn, SEMAPHORE * if (use_existing_ai) { // Store the current dialogue off the existing actor intent a_speakint = (SPEAKINTENT *)a_intent_p->a_data; - ys_dll_add_tail(a_speakint->si_diaglist, &a_dialogue, sizeof(a_dialogue)); + a_speakint->si_diaglist.push_back(a_dialogue); } else { // Create a new actor intent a_intent.a_itype = INTENT_SPEAK; a_intent.a_idone = 0; a_intent.a_iflags = 0; + a_intent.createData(); - a_speakint = (SPEAKINTENT *)malloc(sizeof(*a_speakint)); - if (a_speakint == NULL) { - return FAILURE; - } - - a_speakint->si_init = 0; - a_speakint->si_diaglist = ys_dll_create(); + a_speakint = (SPEAKINTENT *)a_intent.a_data; a_speakint->si_last_action = actor->action; - a_intent.a_data = a_speakint; + a_speakint->si_diaglist.push_back(a_dialogue); - ys_dll_add_tail(a_speakint->si_diaglist, &a_dialogue, sizeof(a_dialogue)); - ys_dll_add_tail(actor->a_intentlist, &a_intent, sizeof(a_intent)); + actor->a_intentlist.push_back(a_intent); } if (sem != NULL) { @@ -462,8 +440,8 @@ int Actor::speak(int index, const char *d_string, uint16 d_voice_rn, SEMAPHORE * } int Actor::handleSpeakIntent(ACTOR *actor, SPEAKINTENT *a_speakint, int *complete_p, int msec) { - YS_DL_NODE *a_dnode; - YS_DL_NODE *a_dnext; + ActorDialogList::iterator actorDialogIterator; + ActorDialogList::iterator nextActorDialogIterator; ACTORDIALOGUE *a_dialogue; ACTORDIALOGUE *a_dialogue2; long carry_time; @@ -479,9 +457,9 @@ int Actor::handleSpeakIntent(ACTOR *actor, SPEAKINTENT *a_speakint, int *complet } // Process actor dialogue list - a_dnode = ys_dll_head(a_speakint->si_diaglist); - if (a_dnode != NULL) { - a_dialogue = (ACTORDIALOGUE *)ys_dll_get_data(a_dnode); + actorDialogIterator = a_speakint->si_diaglist.begin(); + if (actorDialogIterator != a_speakint->si_diaglist.end()) { + a_dialogue = actorDialogIterator.operator->(); if (!a_dialogue->d_playing) { // Dialogue voice hasn't played yet - play it now _vm->_sndRes->playVoice(a_dialogue->d_voice_rn); @@ -502,19 +480,18 @@ int Actor::handleSpeakIntent(ACTOR *actor, SPEAKINTENT *a_speakint, int *complet carry_time = a_dialogue->d_time; - a_dnext = ys_dll_next(a_dnode); - if (a_dnext != NULL) { - a_dialogue2 = (ACTORDIALOGUE *)ys_dll_get_data(a_dnode); + nextActorDialogIterator = actorDialogIterator; + ++nextActorDialogIterator; + if (nextActorDialogIterator != a_speakint->si_diaglist.end()) { + a_dialogue2 = nextActorDialogIterator.operator->(); a_dialogue2->d_time -= carry_time; } - ys_dll_delete(a_dnode); - // Check if there are any dialogue nodes left. If not, // flag this speech intent as complete - a_dnode = ys_dll_head(a_speakint->si_diaglist); - if (a_dnode == NULL) { + actorDialogIterator = a_speakint->si_diaglist.erase(actorDialogIterator); + if (actorDialogIterator != a_speakint->si_diaglist.end()) { intent_complete = 1; } } @@ -597,7 +574,7 @@ int Actor::setDefaultAction(int index, int action_n, uint16 action_flags) { } ACTOR *Actor::lookupActor(int index) { - YS_DL_NODE *node; + ActorList::iterator actorIterator; ACTOR *actor; if (!_initialized) { @@ -608,12 +585,12 @@ ACTOR *Actor::lookupActor(int index) { return NULL; } - if (_tbl[index] == NULL) { + if (_tbl[index] == zeroActorIterator) { return NULL; } - node = _tbl[index]; - actor = (ACTOR *)ys_dll_get_data(node); + actorIterator = _tbl[index]; + actor = actorIterator.operator->(); return actor; } @@ -637,7 +614,7 @@ int Actor::loadActorSpriteIndex(ACTOR * actor, int si_rn, int *last_frame_p) { debug(0, "Sprite resource contains %d sprite actions.", s_action_ct); action_p = (ACTORACTION *)malloc(sizeof(ACTORACTION) * s_action_ct); - MemoryReadStream readS(res_p, res_len); + MemoryReadStreamEndian readS(res_p, res_len, IS_BIG_ENDIAN); if (action_p == NULL) { warning("Couldn't allocate memory for sprite actions"); @@ -650,8 +627,8 @@ int Actor::loadActorSpriteIndex(ACTOR * actor, int si_rn, int *last_frame_p) { for (i = 0; i < s_action_ct; i++) { for (orient = 0; orient < 4; orient++) { // Load all four orientations - action_p[i].dir[orient].frame_index = readS.readUint16LE(); - action_p[i].dir[orient].frame_count = readS.readUint16LE(); + action_p[i].dir[orient].frame_index = readS.readUint16(); + action_p[i].dir[orient].frame_count = readS.readUint16(); if (action_p[i].dir[orient].frame_index > last_frame) { last_frame = action_p[i].dir[orient].frame_index; } @@ -671,7 +648,7 @@ int Actor::loadActorSpriteIndex(ACTOR * actor, int si_rn, int *last_frame_p) { } int Actor::deleteActor(int index) { - YS_DL_NODE *node; + ActorList::iterator actorIterator; ACTOR *actor; if (!_initialized) { @@ -682,18 +659,19 @@ int Actor::deleteActor(int index) { return FAILURE; } - if (_tbl[index] == NULL) { + actorIterator = _tbl[index]; + + if (actorIterator == zeroActorIterator) { return FAILURE; } - node = _tbl[index]; - actor = (ACTOR *)ys_dll_get_data(node); + actor = actorIterator.operator->(); _vm->_sprite->freeSprite(actor->sl_p); - ys_dll_delete(node); + _list.erase(actorIterator); - _tbl[index] = NULL; + _tbl[index] = zeroActorIterator; return SUCCESS; } @@ -701,8 +679,7 @@ int Actor::deleteActor(int index) { int Actor::walkTo(int id, const Point *walk_pt, uint16 flags, SEMAPHORE *sem) { ACTORINTENT actor_intent; WALKINTENT *walk_intent; - WALKINTENT zero_intent; - YS_DL_NODE *node; + ActorList::iterator actorIterator; ACTOR *actor; assert(_initialized); @@ -712,19 +689,18 @@ int Actor::walkTo(int id, const Point *walk_pt, uint16 flags, SEMAPHORE *sem) { return FAILURE; } - if (_tbl[id] == NULL) { + if (_tbl[id] == zeroActorIterator) { return FAILURE; } - node = _tbl[id]; - actor = (ACTOR *)ys_dll_get_data(node); + actorIterator = _tbl[id]; + actor = actorIterator.operator->(); - walk_intent = (WALKINTENT *)malloc(sizeof(*walk_intent)); - if (walk_intent == NULL) { - return MEM; - } - - *walk_intent = zero_intent; + actor_intent.a_itype = INTENT_PATH; + actor_intent.a_iflags = 0; + actor_intent.createData(); + + walk_intent = (WALKINTENT*)actor_intent.a_data; walk_intent->wi_flags = flags; walk_intent->sem_held = 1; @@ -734,11 +710,7 @@ int Actor::walkTo(int id, const Point *walk_pt, uint16 flags, SEMAPHORE *sem) { walk_intent->wi_init = 0; walk_intent->dst_pt = *walk_pt; - actor_intent.a_itype = INTENT_PATH; - actor_intent.a_iflags = 0; - actor_intent.a_data = walk_intent; - - ys_dll_add_tail(actor->a_intentlist, &actor_intent, sizeof(actor_intent)); + actor->a_intentlist.push_back(actor_intent); if (sem != NULL) { _vm->_script->SThreadHoldSem(sem); @@ -754,19 +726,18 @@ int Actor::setPathNode(WALKINTENT *walk_int, Point *src_pt, Point *dst_pt, SEMAP walk_int->org = *src_pt; assert((walk_int != NULL) && (src_pt != NULL) && (dst_pt != NULL)); - assert(walk_int->nodelist != NULL); new_node.node_pt = *dst_pt; new_node.calc_flag = 0; - - ys_dll_add_tail(walk_int->nodelist, &new_node, sizeof(new_node)); - + + walk_int->nodelist.push_back(new_node); + return SUCCESS; } int Actor::handleWalkIntent(ACTOR *actor, WALKINTENT *a_walkint, int *complete_p, int delta_time) { - YS_DL_NODE *walk_p; - YS_DL_NODE *next_p; + WalkNodeList::iterator walkNodeIterator; + WalkNodeList::iterator nextWalkNodeIterator; WALKNODE *node_p; int dx; @@ -790,7 +761,6 @@ int Actor::handleWalkIntent(ACTOR *actor, WALKINTENT *a_walkint, int *complete_p // Initialize walk intent if (!a_walkint->wi_init) { - a_walkint->nodelist = ys_dll_create(); setPathNode(a_walkint, &actor->a_pt, &a_walkint->dst_pt, a_walkint->sem); setDefaultAction(actor->id, ACTION_IDLE, ACTION_NONE); a_walkint->wi_init = 1; @@ -798,10 +768,10 @@ int Actor::handleWalkIntent(ACTOR *actor, WALKINTENT *a_walkint, int *complete_p assert(a_walkint->wi_active); - walk_p = ys_dll_head(a_walkint->nodelist); - next_p = ys_dll_next(walk_p); + walkNodeIterator = a_walkint->nodelist.begin(); + nextWalkNodeIterator = walkNodeIterator; - node_p = (WALKNODE *)ys_dll_get_data(walk_p); + node_p = walkNodeIterator.operator->(); if (node_p->calc_flag == 0) { @@ -814,7 +784,7 @@ int Actor::handleWalkIntent(ACTOR *actor, WALKINTENT *a_walkint, int *complete_p debug(0, "Vertical paths not implemented."); - ys_dll_delete(walk_p); + a_walkint->nodelist.erase(walkNodeIterator); a_walkint->wi_active = 0; // Release path semaphore @@ -883,7 +853,7 @@ int Actor::handleWalkIntent(ACTOR *actor, WALKINTENT *a_walkint, int *complete_p int exitNum; debug(2, "Path complete."); - ys_dll_delete(walk_p); + a_walkint->nodelist.erase(walkNodeIterator); a_walkint->wi_active = 0; // Release path semaphore @@ -913,28 +883,32 @@ int Actor::handleWalkIntent(ACTOR *actor, WALKINTENT *a_walkint, int *complete_p actor->s_pt.x = actor->a_pt.x >> 2; actor->s_pt.y = actor->a_pt.y >> 2; - if (path_slope < 0) { - ys_dll_reorder_up(_list, actor->node, zCompare); - + ActorList::iterator actorIterator; + if (_list.locate(actor, actorIterator)) { + if (path_slope < 0) { + _list.reorderUp(actorIterator, actorCompare); + } else { + _list.reorderDown(actorIterator, actorCompare); + } } else { - ys_dll_reorder_down(_list, actor->node, zCompare); + error("Actor::handleWalkIntent() actor not found list"); } return SUCCESS; } int Actor::move(int index, const Point *move_pt) { - YS_DL_NODE *node; + ActorList::iterator actorIterator; ACTOR *actor; int move_up = 0; - node = _tbl[index]; - if (node == NULL) { + actorIterator = _tbl[index]; + if (actorIterator == zeroActorIterator) { return FAILURE; } - actor = (ACTOR *)ys_dll_get_data(node); + actor = actorIterator.operator->(); if (move_pt->y < actor->a_pt.y) { move_up = 1; @@ -946,25 +920,24 @@ int Actor::move(int index, const Point *move_pt) { AtoS(&actor->s_pt, &actor->a_pt); if (move_up) { - ys_dll_reorder_up(_list, actor->node, zCompare); + _list.reorderUp(actorIterator, actorCompare); } else { - - ys_dll_reorder_down(_list, actor->node, zCompare); + _list.reorderDown(actorIterator, actorCompare); } return SUCCESS; } int Actor::moveRelative(int index, const Point *move_pt) { - YS_DL_NODE *node; + ActorList::iterator actorIterator; ACTOR *actor; - node = _tbl[index]; - if (node == NULL) { + actorIterator = _tbl[index]; + if (actorIterator == zeroActorIterator) { return FAILURE; } - actor = (ACTOR *)ys_dll_get_data(node); + actor = actorIterator.operator->(); actor->a_pt.x += move_pt->x; actor->a_pt.y += move_pt->y; @@ -972,29 +945,14 @@ int Actor::moveRelative(int index, const Point *move_pt) { AtoS(&actor->s_pt, &actor->a_pt); if (actor->a_pt.y < 0) { - - ys_dll_reorder_up(_list, actor->node, zCompare); + _list.reorderUp(actorIterator, actorCompare); } else { - - ys_dll_reorder_down(_list, actor->node, zCompare); - + _list.reorderDown(actorIterator, actorCompare); } return SUCCESS; } -static int zCompare(const void *elem1, const void *elem2) { - const ACTOR *actor1 = (const ACTOR *) elem1; - const ACTOR *actor2 = (const ACTOR *) elem2; - - if (actor1->a_pt.y == actor2->a_pt.y) { - return 0; - } else if (actor1->a_pt.y < actor2->a_pt.y) { - return -1; - } else { - return 1; - } -} int Actor::AtoS(Point *screen, const Point *actor) { screen->x = (actor->x / ACTOR_LMULT); diff --git a/saga/actor.h b/saga/actor.h index a1a6b7cafc..4df31a70a4 100644 --- a/saga/actor.h +++ b/saga/actor.h @@ -26,8 +26,9 @@ #ifndef SAGA_ACTOR_H__ #define SAGA_ACTOR_H__ -#include "saga/yslib.h" #include "saga/sprite.h" +#include "saga/actordata.h" +#include "saga/list.h" namespace Saga { @@ -87,6 +88,16 @@ struct ACTORACTION { ACTORACTIONITEM dir[4]; }; +struct WALKNODE { + int calc_flag; + Point node_pt; + WALKNODE() { + calc_flag = 0; + } +}; + +typedef Common::List WalkNodeList; + struct WALKINTENT { int wi_active; uint16 wi_flags; @@ -99,24 +110,48 @@ struct WALKINTENT { Point cur; Point dst_pt; - YS_DL_LIST *nodelist; + WalkNodeList nodelist; int sem_held; SEMAPHORE *sem; - WALKINTENT() { memset(this, 0, sizeof(*this)); } + WALKINTENT() { + wi_active = 0; + wi_flags = 0; + wi_init = 0; + + time = 0; + slope = 0; + x_dir = 0; + + sem_held = 0; + sem = NULL; + } }; -struct WALKNODE { - int calc_flag; - Point node_pt; + +struct ACTORDIALOGUE { + int d_playing; + const char *d_string; + uint16 d_voice_rn; + long d_time; + int d_sem_held; + SEMAPHORE *d_sem; + ACTORDIALOGUE() { memset(this, 0, sizeof(*this)); } }; +typedef Common::List ActorDialogList; + struct SPEAKINTENT { int si_init; uint16 si_flags; int si_last_action; - YS_DL_LIST *si_diaglist; /* Actor dialogue list */ + ActorDialogList si_diaglist; /* Actor dialogue list */ + SPEAKINTENT() { + si_init = 0; + si_flags = 0; + si_last_action = 0; + } }; struct ACTORINTENT { @@ -125,9 +160,42 @@ struct ACTORINTENT { int a_idone; void *a_data; + void createData() { + assert(a_data == NULL); + + if(INTENT_SPEAK == a_itype) { + a_data = new SPEAKINTENT; + } + else + if(INTENT_PATH == a_itype) { + a_data = new WALKINTENT; + } + } + void deleteData() { + + if(INTENT_SPEAK == a_itype) { + SPEAKINTENT *a_speakint; + + assert(a_data); + a_speakint = (SPEAKINTENT *)a_data; + delete a_speakint; + } + else + if(INTENT_PATH == a_itype) { + WALKINTENT *a_walkint; + + assert(a_data); + a_walkint = (WALKINTENT *)a_data; + delete a_walkint; + } + a_data = NULL; + } + ACTORINTENT() { memset(this, 0, sizeof(*this)); } }; +typedef Common::List ActorIntentList; + struct ACTOR { int id; // Actor id int name_i; // Actor's index in actor name string list @@ -151,7 +219,7 @@ struct ACTOR { // intent before moving on to the next; thus actor movements, esp // as described from scripts, can be serialized - YS_DL_LIST *a_intentlist; + ActorIntentList a_intentlist; // WALKPATH path; @@ -165,19 +233,30 @@ struct ACTOR { ACTORACTION *act_tbl; // Action lookup table int action_ct; // Number of actions in the action LUT - YS_DL_NODE *node; // Actor's node in the actor list - ACTOR() { memset(this, 0, sizeof(*this)); } + ACTOR() { + id = 0; + name_i = 0; + flags = 0; + sl_rn = 0; + si_rn = 0; + sl_p = 0; + idle_time = 0; + orient = 0; + speaking = 0; + a_dcolor = 0; + def_action = 0; + def_action_flags = 0; + action = 0; + action_flags = 0; + action_frame = 0; + action_time = 0; + act_tbl = NULL; + action_ct = NULL; + } }; -struct ACTORDIALOGUE { - int d_playing; - const char *d_string; - uint16 d_voice_rn; - long d_time; - int d_sem_held; - SEMAPHORE *d_sem; - ACTORDIALOGUE() { memset(this, 0, sizeof(*this)); } -}; +typedef SortedList ActorList; + struct ACTIONTIMES { int action; @@ -235,9 +314,9 @@ private: bool _initialized; RSCFILE_CONTEXT *_actorContext; uint16 _count; - int *_aliasTbl; - YS_DL_NODE **_tbl; - YS_DL_LIST *_list; + int _aliasTbl[ACTORCOUNT]; + ActorList::iterator _tbl[ACTORCOUNT]; + ActorList _list; }; } // End of namespace Saga diff --git a/saga/animation.cpp b/saga/animation.cpp index 7768ad2294..b92d81f296 100644 --- a/saga/animation.cpp +++ b/saga/animation.cpp @@ -31,6 +31,7 @@ #include "saga/render.h" #include "saga/animation.h" +#include "saga/stream.h" namespace Saga { @@ -105,7 +106,7 @@ int Anim::load(const byte *anim_resdata, size_t anim_resdata_len, uint16 *anim_i getFrameOffset(anim_resdata, anim_resdata_len, i + 1, &new_anim->frame_offsets[i]); } } else { - new_anim->cur_frame_p = anim_resdata + SAGA_FRAME_HEADER_LEN; + new_anim->cur_frame_p = anim_resdata + SAGA_FRAME_HEADER_LEN; // ? len - may vary new_anim->cur_frame_len = anim_resdata_len - SAGA_FRAME_HEADER_LEN; getNumFrames(anim_resdata, anim_resdata_len, &new_anim->n_frames); } @@ -372,12 +373,13 @@ int Anim::getNumFrames(const byte *anim_resource, size_t anim_resource_len, uint if (!_initialized) { return FAILURE; } + - MemoryReadStream readS(anim_resource, anim_resource_len); + MemoryReadStreamEndian readS(anim_resource, anim_resource_len, IS_BIG_ENDIAN); - ah.magic = readS.readUint16LE(); - ah.screen_w = readS.readUint16LE(); - ah.screen_h = readS.readUint16LE(); + ah.magic = readS.readUint16LE(); // cause ALWAYS LE + ah.screen_w = readS.readUint16(); + ah.screen_h = readS.readUint16(); ah.unknown06 = readS.readByte(); ah.unknown07 = readS.readByte(); @@ -394,7 +396,7 @@ int Anim::getNumFrames(const byte *anim_resource, size_t anim_resource_len, uint } magic = *(anim_resource + offset); - if (magic == SAGA_FRAME_HEADER_MAGIC) { + if (magic == SAGA_FRAME_START) { *n_frames = x; return SUCCESS; } @@ -435,11 +437,11 @@ int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_ return FAILURE; } - MemoryReadStream headerReadS(resdata, resdata_len); + MemoryReadStreamEndian headerReadS(resdata, resdata_len, IS_BIG_ENDIAN); // Read animation header ah.magic = headerReadS.readUint16LE(); - ah.screen_w = headerReadS.readUint16LE(); - ah.screen_h = headerReadS.readUint16LE(); + ah.screen_w = headerReadS.readUint16(); + ah.screen_h = headerReadS.readUint16(); ah.unknown06 = headerReadS.readByte(); ah.unknown07 = headerReadS.readByte(); ah.nframes = headerReadS.readByte(); @@ -456,22 +458,21 @@ int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_ return FAILURE; } - // Read frame header MemoryReadStream readS(resdata + frame_offset, resdata_len - frame_offset); // Check for frame magic byte magic = readS.readByte(); - if (magic != SAGA_FRAME_HEADER_MAGIC) { + if (magic != SAGA_FRAME_START) { warning("ITE_DecodeFrame: Invalid frame offset"); return FAILURE; } - // For some strange reason, the animation header is in little - // endian format, but the actual RLE encoded frame data, - // including the frame header, is in big endian format. fh.x_start = readS.readUint16BE(); - fh.y_start = readS.readByte(); + if (IS_MAC_VERSION) + fh.y_start = readS.readUint16BE(); + else + fh.y_start = readS.readByte(); readS.readByte(); /* Skip pad byte */ fh.x_pos = readS.readUint16BE(); fh.y_pos = readS.readUint16BE(); @@ -481,14 +482,25 @@ int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_ x_start = fh.x_start; y_start = fh.y_start; +#if 1 +#define VALIDATE_WRITE_POINTER \ + if ((write_p < buf) || (write_p >= (buf + screen_w * screen_h))) { \ + warning("VALIDATE_WRITE_POINTER: write_p=%x buf=%x", write_p, buf); \ + return FAILURE; \ + } +#else +#define VALIDATE_WRITE_POINTER +#endif + // Setup write pointer to the draw origin write_p = (buf + (y_start * screen_w) + x_start); + VALIDATE_WRITE_POINTER; // Begin RLE decompression to output buffer do { mark_byte = readS.readByte(); switch (mark_byte) { - case 0x10: // Long Unencoded Run + case SAGA_FRAME_LONG_UNCOMPRESSED_RUN: // Long Unencoded Run runcount = readS.readSint16BE(); for (i = 0; i < runcount; i++) { data_byte = readS.readByte(); @@ -496,30 +508,39 @@ int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_ *write_p = data_byte; } write_p++; + VALIDATE_WRITE_POINTER; } continue; break; - case 0x20: // Long encoded run + case SAGA_FRAME_LONG_COMPRESSED_RUN: // Long encoded run runcount = readS.readSint16BE(); data_byte = readS.readByte(); for (i = 0; i < runcount; i++) { *write_p++ = data_byte; + VALIDATE_WRITE_POINTER; } continue; break; - case 0x2F: // End of row + case SAGA_FRAME_ROW_END: // End of row x_vector = readS.readSint16BE(); - new_row = readS.readByte(); + + if (IS_MAC_VERSION) + new_row = readS.readSint16BE(); + else + new_row = readS.readByte(); + // Set write pointer to the new draw origin write_p = buf + ((y_start + new_row) * screen_w) + x_start + x_vector; + VALIDATE_WRITE_POINTER; continue; break; - case 0x30: // Reposition command + case SAGA_FRAME_REPOSITION: // Reposition command x_vector = readS.readSint16BE(); write_p += x_vector; + VALIDATE_WRITE_POINTER; continue; break; - case 0x3F: // End of frame marker + case SAGA_FRAME_END: // End of frame marker return SUCCESS; break; default: @@ -530,22 +551,24 @@ int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_ control_ch = mark_byte & 0xC0U; param_ch = mark_byte & 0x3FU; switch (control_ch) { - case 0xC0: // 1100 0000 + case SAGA_FRAME_EMPTY_RUN: // 1100 0000 // Run of empty pixels runcount = param_ch + 1; write_p += runcount; + VALIDATE_WRITE_POINTER; continue; break; - case 0x80: // 1000 0000 + case SAGA_FRAME_COMPRESSED_RUN: // 1000 0000 // Run of compressed data runcount = param_ch + 1; data_byte = readS.readByte(); for (i = 0; i < runcount; i++) { *write_p++ = data_byte; + VALIDATE_WRITE_POINTER; } continue; break; - case 0x40: // 0100 0000 + case SAGA_FRAME_UNCOMPRESSED_RUN: // 0100 0000 // Uncompressed run runcount = param_ch + 1; for (i = 0; i < runcount; i++) { @@ -554,6 +577,7 @@ int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_ *write_p = data_byte; } write_p++; + VALIDATE_WRITE_POINTER; } continue; break; @@ -586,7 +610,7 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte * size_t in_ch_offset; - MemoryReadStream readS(thisf_p, thisf_len); + MemoryReadStreamEndian readS(thisf_p, thisf_len, !IS_BIG_ENDIAN); // RLE has inversion BE<>LE byte *outbuf_p = decode_buf; byte *outbuf_endp = (decode_buf + decode_buf_len) - 1; @@ -616,13 +640,13 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte * return FAILURE; } - param1 = readS.readUint16BE(); - param2 = readS.readUint16BE(); + param1 = readS.readUint16(); + param2 = readS.readUint16(); readS.readByte(); // skip 1? - param3 = readS.readUint16BE(); - param4 = readS.readUint16BE(); - param5 = readS.readUint16BE(); - param6 = readS.readUint16BE(); + param3 = readS.readUint16(); + param4 = readS.readUint16(); + param5 = readS.readUint16(); + param6 = readS.readUint16(); x_origin = param1; y_origin = param2; @@ -639,8 +663,8 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte * continue; } break; - case 0x10: // Long Unencoded Run - runcount = readS.readSint16BE(); + case SAGA_FRAME_LONG_UNCOMPRESSED_RUN: // Long Unencoded Run + runcount = readS.readSint16(); if (thisf_len - readS.pos() < runcount) { warning("0x%02X: Input buffer underrun", in_ch); return FAILURE; @@ -672,13 +696,13 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte * readS.readByte(); continue; break; - case 0x20: // Long compressed run + case SAGA_FRAME_LONG_COMPRESSED_RUN: // Long compressed run if (thisf_len - readS.pos() <= 3) { warning("0x%02X: Input buffer underrun", in_ch); return FAILURE; } - runcount = readS.readSint16BE(); + runcount = readS.readSint16(); data_pixel = readS.readByte(); for (c = 0; c < runcount; c++) { @@ -689,27 +713,27 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte * continue; break; - case 0x2F: // End of row + case SAGA_FRAME_ROW_END: // End of row if (thisf_len - readS.pos() <= 4) { return FAILURE; } - x_vector = readS.readSint16BE(); - new_row = readS.readSint16BE(); + x_vector = readS.readSint16(); + new_row = readS.readSint16(); outbuf_p = decode_buf + ((y_origin + new_row) * di.logical_w) + x_origin + x_vector; outbuf_remain = (outbuf_endp - outbuf_p) + 1; continue; break; - case 0x30: // Reposition command + case SAGA_FRAME_REPOSITION: // Reposition command if (thisf_len - readS.pos() < 2) { return FAILURE; } - x_vector = readS.readSint16BE(); + x_vector = readS.readSint16(); if (((x_vector > 0) && ((size_t) x_vector > outbuf_remain)) || (-x_vector > outbuf_p - decode_buf)) { - warning("0x30: Invalid x_vector"); + warning("SAGA_FRAME_REPOSITION: Invalid x_vector"); return FAILURE; } @@ -718,8 +742,8 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte * continue; break; - case 0x3F: // 68: Frame end marker - debug(1, "0x3F: Frame end marker"); + case SAGA_FRAME_END: // Frame end marker + debug(1, "SAGA_FRAME_END: Frame end marker"); if (decoded_data && (thisf_len - readS.pos() > 0)) { *nextf_p = thisf_p + readS.pos(); *nextf_len = thisf_len - readS.pos(); @@ -740,7 +764,7 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte * param_ch = in_ch & 0x3f; switch (control_ch) { - case 0xC0: // Run of empty pixels + case SAGA_FRAME_EMPTY_RUN: // Run of empty pixels runcount = param_ch + 1; if (outbuf_remain < runcount) { return FAILURE; @@ -750,7 +774,7 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte * outbuf_remain -= runcount; continue; break; - case 0x80: // Run of compressed data + case SAGA_FRAME_COMPRESSED_RUN: // Run of compressed data runcount = param_ch + 1; if ((outbuf_remain < runcount) || (thisf_len - readS.pos() <= 1)) { return FAILURE; @@ -765,7 +789,7 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte * outbuf_remain -= runcount; continue; break; - case 0x40: // Uncompressed run + case SAGA_FRAME_UNCOMPRESSED_RUN: // Uncompressed run runcount = param_ch + 1; if ((outbuf_remain < runcount) || (thisf_len - readS.pos() < runcount)) { return FAILURE; @@ -809,12 +833,13 @@ int Anim::getFrameOffset(const byte *resdata, size_t resdata_len, uint16 find_fr return FAILURE; } - MemoryReadStream readS(resdata, resdata_len); + + MemoryReadStreamEndian readS(resdata, resdata_len, IS_BIG_ENDIAN); // Read animation header ah.magic = readS.readUint16LE(); - ah.screen_w = readS.readUint16LE(); - ah.screen_h = readS.readUint16LE(); + ah.screen_w = readS.readUint16(); + ah.screen_h = readS.readUint16(); ah.unknown06 = readS.readByte(); ah.unknown07 = readS.readByte(); ah.nframes = readS.readByte(); @@ -828,9 +853,11 @@ int Anim::getFrameOffset(const byte *resdata, size_t resdata_len, uint16 find_fr return FAILURE; } + readS._bigEndian = !IS_BIG_ENDIAN; // RLE has inversion BE<>LE + for (current_frame = 1; current_frame < find_frame; current_frame++) { magic = readS.readByte(); - if (magic != SAGA_FRAME_HEADER_MAGIC) { + if (magic != SAGA_FRAME_START) { // Frame sync failure. Magic Number not found return FAILURE; } @@ -839,33 +866,36 @@ int Anim::getFrameOffset(const byte *resdata, size_t resdata_len, uint16 find_fr for (i = 0; i < SAGA_FRAME_HEADER_LEN; i++) readS.readByte(); + // For some strange reason, the animation header is in little // endian format, but the actual RLE encoded frame data, // including the frame header, is in big endian format. */ do { mark_byte = readS.readByte(); +// debug(7, "_pos=%x mark_byte=%x", readS.pos(), mark_byte); + switch (mark_byte) { - case 0x3F: // End of frame marker + case SAGA_FRAME_END: // End of frame marker continue; break; - case 0x30: // Reposition command - readS.readByte(); - readS.readByte(); + case SAGA_FRAME_REPOSITION: // Reposition command + readS.readSint16BE(); continue; break; - case 0x2F: // End of row marker - readS.readByte(); - readS.readByte(); - readS.readByte(); + case SAGA_FRAME_ROW_END: // End of row marker + readS.readSint16BE(); + if (IS_MAC_VERSION) + readS.readSint16BE(); + else + readS.readByte(); continue; break; - case 0x20: // Long compressed run marker - readS.readByte(); - readS.readByte(); + case SAGA_FRAME_LONG_COMPRESSED_RUN: // Long compressed run marker + readS.readSint16BE(); readS.readByte(); continue; break; - case 0x10: // (16) 0001 0000 + case SAGA_FRAME_LONG_UNCOMPRESSED_RUN: // (16) 0001 0000 // Long Uncompressed Run runcount = readS.readSint16BE(); for (i = 0; i < runcount; i++) @@ -879,16 +909,16 @@ int Anim::getFrameOffset(const byte *resdata, size_t resdata_len, uint16 find_fr // Mask all but two high order (control) bits control = mark_byte & 0xC0; switch (control) { - case 0xC0: + case SAGA_FRAME_EMPTY_RUN: // Run of empty pixels continue; break; - case 0x80: + case SAGA_FRAME_COMPRESSED_RUN: // Run of compressed data readS.readByte(); // Skip data byte continue; break; - case 0x40: + case SAGA_FRAME_UNCOMPRESSED_RUN: // Uncompressed run runcount = (mark_byte & 0x3f) + 1; for (i = 0; i < runcount; i++) @@ -900,7 +930,7 @@ int Anim::getFrameOffset(const byte *resdata, size_t resdata_len, uint16 find_fr return FAILURE; break; } - } while (mark_byte != 63); + } while (mark_byte != SAGA_FRAME_END); } *frame_offset_p = readS.pos(); diff --git a/saga/animation.h b/saga/animation.h index 4f41d8c75a..1fafe892f3 100644 --- a/saga/animation.h +++ b/saga/animation.h @@ -31,8 +31,17 @@ namespace Saga { #define MAX_ANIMATIONS 7 #define DEFAULT_FRAME_TIME 140 -#define SAGA_FRAME_HEADER_MAGIC 15 -#define SAGA_FRAME_HEADER_LEN 12 +#define SAGA_FRAME_HEADER_LEN (IS_MAC_VERSION ? 13 : 12) + +#define SAGA_FRAME_START 0xF +#define SAGA_FRAME_END 0x3F +#define SAGA_FRAME_REPOSITION 0x30 +#define SAGA_FRAME_ROW_END 0x2F +#define SAGA_FRAME_LONG_COMPRESSED_RUN 0x20 +#define SAGA_FRAME_LONG_UNCOMPRESSED_RUN 0x10 +#define SAGA_FRAME_COMPRESSED_RUN 0x80 +#define SAGA_FRAME_UNCOMPRESSED_RUN 0x40 +#define SAGA_FRAME_EMPTY_RUN 0xC0 // All animation resources begin with an ANIMATION_HEADER // at 0x00, followed by a RLE code stream diff --git a/saga/events.cpp b/saga/events.cpp index f1bbdcc564..a1984f21b2 100644 --- a/saga/events.cpp +++ b/saga/events.cpp @@ -27,7 +27,6 @@ #include "saga/saga.h" #include "saga/gfx.h" -#include "saga/yslib.h" #include "saga/animation.h" #include "saga/console.h" @@ -46,10 +45,7 @@ namespace Saga { Events::Events(SagaEngine *vm) : _vm(vm), _initialized(false) { debug(0, "Initializing event subsystem..."); - _eventList = ys_dll_create(); - - if (_eventList) - _initialized = true; + _initialized = true; } Events::~Events(void) { @@ -61,9 +57,6 @@ Events::~Events(void) { // First advances event times, then processes each event with the appropriate // handler depending on the type of event. int Events::handleEvents(long msec) { - YS_DL_NODE *walk_node; - YS_DL_NODE *next_node; - EVENT *event_p; long delta_time; @@ -73,11 +66,8 @@ int Events::handleEvents(long msec) { processEventTime(msec); // Process each event in list - for (walk_node = ys_dll_head(_eventList); walk_node != NULL; walk_node = next_node) { - event_p = (EVENT *)ys_dll_get_data(walk_node); - - // Save next event in case current event is handled and removed - next_node = ys_dll_next(walk_node); + for (EventList::iterator eventi = _eventList.begin(); eventi != _eventList.end(); ++eventi) { + event_p = (EVENT *)eventi.operator->(); // Call the appropriate event handler for the specific event type switch (event_p->type) { @@ -109,19 +99,18 @@ int Events::handleEvents(long msec) { if ((result == EVENT_DELETE) || (result == EVENT_INVALIDCODE)) { // If there is no event chain, delete the base event. if (event_p->chain == NULL) { - ys_dll_delete(walk_node); + eventi=_eventList.eraseAndPrev(eventi); } else { // If there is an event chain present, move the next event // in the chain up, adjust it by the previous delta time, - // and reprocess the event by adjusting next_node. */ + // and reprocess the event */ delta_time = event_p->time; + EVENT *from_chain=event_p->chain; + memcpy(event_p, from_chain,sizeof *event_p); + free(from_chain); - ys_dll_replace(walk_node, event_p->chain, sizeof *event_p); - - event_p = (EVENT *)ys_dll_get_data(walk_node); event_p->time += delta_time; - - next_node = walk_node; + --eventi; } } else if (result == EVENT_BREAK) { break; @@ -426,17 +415,10 @@ int Events::handleInterval(EVENT *event) { // Schedules an event in the event list; returns a pointer to the scheduled // event suitable for chaining if desired. EVENT *Events::queue(EVENT *event) { - YS_DL_NODE *new_node; EVENT *queued_event; event->chain = NULL; - new_node = ys_dll_add_tail(_eventList, event, sizeof *event); - - if (new_node == NULL) { - return NULL; - } - - queued_event = (EVENT *)ys_dll_get_data(new_node); + queued_event = _eventList.pushBack(*event).operator->(); initializeEvent(queued_event); @@ -490,16 +472,13 @@ int Events::initializeEvent(EVENT *event) { } int Events::clearList() { - YS_DL_NODE *walk_node; - YS_DL_NODE *next_node; EVENT *chain_walk; EVENT *next_chain; EVENT *event_p; // Walk down event list - for (walk_node = ys_dll_head(_eventList); walk_node != NULL; walk_node = next_node) { - next_node = ys_dll_next(walk_node); - event_p = (EVENT *)ys_dll_get_data(walk_node); + for (EventList::iterator eventi = _eventList.begin(); eventi != _eventList.end(); ++eventi) { + event_p = (EVENT *)eventi.operator->(); // Only remove events not marked NODESTROY (engine events) if (!(event_p->code & NODESTROY)) { @@ -508,7 +487,7 @@ int Events::clearList() { next_chain = chain_walk->chain; free(chain_walk); } - ys_dll_delete(walk_node); + eventi=_eventList.eraseAndPrev(eventi); } } @@ -517,24 +496,21 @@ int Events::clearList() { // Removes all events from the list (even NODESTROY) int Events::freeList() { - YS_DL_NODE *walk_node; - YS_DL_NODE *next_node; EVENT *chain_walk; EVENT *next_chain; EVENT *event_p; // Walk down event list - for (walk_node = ys_dll_head(_eventList); walk_node != NULL; walk_node = next_node) { - event_p = (EVENT *)ys_dll_get_data(walk_node); - // Remove any events chained off current node + EventList::iterator eventi = _eventList.begin(); + while (eventi != _eventList.end()) { + event_p = (EVENT *)eventi.operator->(); + + // Remove any events chained off this one */ for (chain_walk = event_p->chain; chain_walk != NULL; chain_walk = next_chain) { next_chain = chain_walk->chain; free(chain_walk); } - - // Delete current node - next_node = ys_dll_next(walk_node); - ys_dll_delete(walk_node); + eventi=_eventList.erase(eventi); } return SUCCESS; @@ -542,12 +518,12 @@ int Events::freeList() { // Walks down the event list, updating event times by 'msec'. int Events::processEventTime(long msec) { - YS_DL_NODE *walk_node; EVENT *event_p; uint16 event_count = 0; - for (walk_node = ys_dll_head(_eventList); walk_node != NULL; walk_node = ys_dll_next(walk_node)) { - event_p = (EVENT *)ys_dll_get_data(walk_node); + for (EventList::iterator eventi = _eventList.begin(); eventi != _eventList.end(); ++eventi) { + event_p = (EVENT *)eventi.operator->(); + event_p->time -= msec; event_count++; diff --git a/saga/events.h b/saga/events.h index 454047f0a1..988a7f4b6b 100644 --- a/saga/events.h +++ b/saga/events.h @@ -26,7 +26,10 @@ #ifndef SAGA_EVENT_H #define SAGA_EVENT_H +#include "saga/list.h" + namespace Saga { + enum EVENT_TYPES { ONESHOT_EVENT, CONTINUOUS_EVENT, @@ -119,6 +122,8 @@ struct EVENT { EVENT() { memset(this, 0, sizeof(*this)); } }; +typedef SortedList EventList; + #define EVENT_WARNINGCOUNT 1000 #define EVENT_MASK 0x00FF @@ -151,7 +156,7 @@ class Events { SagaEngine *_vm; bool _initialized; - YS_DL_LIST *_eventList; + EventList _eventList; }; } // End of namespace Saga diff --git a/saga/font.cpp b/saga/font.cpp index d317b17a94..3fe61688d7 100644 --- a/saga/font.cpp +++ b/saga/font.cpp @@ -29,6 +29,7 @@ #include "saga/game_mod.h" #include "saga/font.h" +#include "saga/stream.h" namespace Saga { @@ -64,20 +65,20 @@ Font::~Font(void) { debug(0, "Font::~Font(): Freeing fonts."); /* - for ( i = 0 ; i < FONT_COUNT ; i ++ ) { - if ( _fonts[i] != NULL ) { - if ( _fonts[i]->normal_loaded ) { - free( _fonts[i]->normal->font_free_p ); - free( _fonts[i]->normal ); + for (i = 0 ; i < FONT_COUNT ; i++) { + if (_fonts[i] != NULL) { + if (_fonts[i]->normal_loaded) { + free(_fonts[i]->normal->font_free_p); + free(_fonts[i]->normal); } - if ( _fonts[i]->outline_loaded ) { - free( _fonts[i]->outline->font_free_p ); - free( _fonts[i]->outline ); + if (_fonts[i]->outline_loaded) { + free(_fonts[i]->outline->font_free_p); + free(_fonts[i]->outline); } } - free( _fonts[i] ); + free(_fonts[i]); } */ } @@ -106,7 +107,7 @@ int Font::loadFont(uint32 font_rn, int font_id) { return FAILURE; } - MemoryReadStream readS(fontres_p, fontres_len); + MemoryReadStreamEndian readS(fontres_p, fontres_len, IS_BIG_ENDIAN); // Create new font structure font = (FONT *)malloc(sizeof *font); @@ -116,9 +117,9 @@ int Font::loadFont(uint32 font_rn, int font_id) { } // Read font header - fh.c_height = readS.readUint16LE(); - fh.c_width = readS.readUint16LE(); - fh.row_length = readS.readUint16LE(); + fh.c_height = readS.readUint16(); + fh.c_width = readS.readUint16(); + fh.row_length = readS.readUint16(); debug(1, "Font::loadFont(): Reading font resource #%d...", font_rn); @@ -140,7 +141,7 @@ int Font::loadFont(uint32 font_rn, int font_id) { normal_font->hdr.row_length = fh.row_length; for (c = 0; c < FONT_CHARCOUNT; c++) { - normal_font->fce[c].index = readS.readUint16LE(); + normal_font->fce[c].index = readS.readUint16(); } for (c = 0; c < FONT_CHARCOUNT; c++) { diff --git a/saga/game.cpp b/saga/game.cpp index d04ac2412f..9f24f651a8 100644 --- a/saga/game.cpp +++ b/saga/game.cpp @@ -50,12 +50,26 @@ GAME_FILEDESC ITEDEMO_GameFiles[] = { GAME_FONTDESC ITEDEMO_GameFonts[] = { {GAME_FONT_SMALL, 0}, {GAME_FONT_MEDIUM, 1} -}; +}; GAME_SOUNDINFO ITEDEMO_GameSound = { GAME_SOUND_VOC, 0, 0, 0 }; +// Inherit the Earth - MAC Wyrmkeep Demo version +GAME_FILEDESC ITEMACDEMO_GameFiles[] = { + {"ITED.RSC", GAME_RESOURCEFILE}, + {"SCRIPTSD.RSC", GAME_SCRIPTFILE}, + {"SOUNDSD.RSC", GAME_SOUNDFILE}, + {"VOICESD.RSC", GAME_VOICEFILE}, + {"MUSICD.RSC", GAME_MUSICFILE} +}; + +GAME_FONTDESC ITEMACDEMO_GameFonts[] = { + {GAME_FONT_MEDIUM, 0}, + {GAME_FONT_SMALL, 2} +}; + // Inherit the Earth - win32 Wyrmkeep Linux Demo version GAME_FILEDESC ITEWINDEMO_GameFiles[] = { {"ITED.RSC", GAME_RESOURCEFILE}, @@ -65,6 +79,11 @@ GAME_FILEDESC ITEWINDEMO_GameFiles[] = { {"MUSICD.RSC", GAME_MUSICFILE} }; +GAME_FONTDESC ITEWINDEMO_GameFonts[] = { + {GAME_FONT_MEDIUM, 0}, + {GAME_FONT_SMALL, 2} +}; + // Inherit the Earth - win32 Wyrmkeep Demo version older release GAME_FILEDESC ITEWINDEMOOld_GameFiles[] = { {"ITED.RSC", GAME_RESOURCEFILE}, @@ -93,6 +112,13 @@ GAME_RESOURCEDESC ITE_Resources = { ITE_DIALOGUE_PANEL }; +GAME_RESOURCEDESC ITEMACDEMO_Resources = { + ITEMACDEMO_SCENE_LUT, // Scene lookup table RN + ITE_SCRIPT_LUT, // Script lookup table RN + ITE_COMMAND_PANEL, + ITE_DIALOGUE_PANEL +}; + GAME_SOUNDINFO ITE_GameSound = { GAME_SOUND_VOC, 0, 0, 0 }; @@ -179,7 +205,26 @@ GAMEDESC GameDescs[] = { ARRAYSIZE(ITEDEMO_GameFonts), ITEDEMO_GameFonts, &ITEDEMO_GameSound, - 0 // features + 0, // features + }, + + // Inherit the earth - MAC Demo version + // Note: it should be before win32 version ??? + { + "ite-demo", + GID_ITE, + GAME_ITE_MACDEMO, + "Inherit the Earth (MAC Demo)", + 320, 200, + 137, + ITE_DEFAULT_SCENE, + &ITEMACDEMO_Resources, + ARRAYSIZE(ITEMACDEMO_GameFiles), + ITEMACDEMO_GameFiles, + ARRAYSIZE(ITEMACDEMO_GameFonts), + ITEMACDEMO_GameFonts, + &ITECD_GameSound, + GF_VOX_VOICES | GF_BIG_ENDIAN_DATA }, // Inherit the earth - Linux Demo version @@ -213,8 +258,8 @@ GAMEDESC GameDescs[] = { &ITE_Resources, ARRAYSIZE(ITEWINDEMOOld_GameFiles), ITEWINDEMO_GameFiles, - ARRAYSIZE(ITECD_GameFonts), - ITECD_GameFonts, + ARRAYSIZE(ITEWINDEMO_GameFonts), + ITEWINDEMO_GameFonts, &ITECD_GameSound, GF_VOX_VOICES }, @@ -465,8 +510,11 @@ int LoadGame(uint16 game_n) { return FAILURE; } - game_filect = GameDescs[game_n].gd_filect; + GameModule.game_number = game_n; + GameModule.gamedesc = &GameDescs[game_n]; + game_filect = GameDescs[game_n].gd_filect; + GameModule.gfile_data = (GAME_FILEDATA *)malloc(game_filect * sizeof *GameModule.gfile_data); if (GameModule.gfile_data == NULL) { return MEM; @@ -493,8 +541,6 @@ int LoadGame(uint16 game_n) { GameModule.gd_fontdescs = GameDescs[game_n].gd_fontdescs; // Finish initialization - GameModule.game_number = game_n; - GameModule.gamedesc = &GameDescs[game_n]; GameModule.game_init = 1; return SUCCESS; @@ -552,11 +598,11 @@ int GAME_GetSceneInfo(GAME_SCENEDESC *gs_desc) { return SUCCESS; } -int GAME_GetGame() { +GAME_IDS GAME_GetGame() { return GameModule.gamedesc->gd_game_id; } -int GAME_GetGameType() { +SAGAGameId GAME_GetGameType() { return GameModule.gamedesc->gd_game_type; } diff --git a/saga/game.h b/saga/game.h index d92a15dcc2..5fc021a535 100644 --- a/saga/game.h +++ b/saga/game.h @@ -47,8 +47,8 @@ struct GAME_FILEDESC { struct GAMEDESC { const char *name; - int gd_game_type; - uint32 gd_game_id; + SAGAGameId gd_game_type; + GAME_IDS gd_game_id; const char *gd_title; int gd_logical_w; int gd_logical_h; diff --git a/saga/game_mod.h b/saga/game_mod.h index 3a8ba044e5..e9a522dd19 100644 --- a/saga/game_mod.h +++ b/saga/game_mod.h @@ -30,13 +30,18 @@ namespace Saga { +#define IS_BIG_ENDIAN ((GAME_GetFeatures() & GF_BIG_ENDIAN_DATA) != 0) +#define IS_MAC_VERSION (GAME_GetGame() == GAME_ITE_MACDEMO) + + enum GAME_IDS { GAME_ITE_DEMO = 0, GAME_ITE_DISK = 1, GAME_ITE_CD = 2, GAME_IHNM_DEMO = 3, GAME_IHNM_CD = 4, - GAME_ITE_WINDEMO = 5 + GAME_ITE_WINDEMO = 5, + GAME_ITE_MACDEMO = 6 }; enum GAME_FILETYPES { @@ -68,7 +73,8 @@ enum GAME_FONT_IDS { }; enum GAME_FEATURES { - GF_VOX_VOICES = 1 + GF_VOX_VOICES = 1, + GF_BIG_ENDIAN_DATA = 2 }; struct GAME_DISPLAYINFO { @@ -109,11 +115,10 @@ int GAME_GetResourceInfo(GAME_RESOURCEDESC *); int GAME_GetSoundInfo(GAME_SOUNDINFO *); int GAME_GetDisplayInfo(GAME_DISPLAYINFO *); int GAME_GetSceneInfo(GAME_SCENEDESC *); -int GAME_GetGame(); -int GAME_GetGameType(); +GAME_IDS GAME_GetGame(); +SAGAGameId GAME_GetGameType(); DetectedGameList GAME_ProbeGame(const FSList &fslist); uint32 GAME_GetFeatures(); - } // End of namespace Saga #endif diff --git a/saga/ihnm_introproc.cpp b/saga/ihnm_introproc.cpp index 6e3ea07e46..e95d3b6fd2 100644 --- a/saga/ihnm_introproc.cpp +++ b/saga/ihnm_introproc.cpp @@ -24,7 +24,6 @@ // "I Have No Mouth" Intro sequence scene procedures #include "saga/saga.h" -#include "saga/yslib.h" #include "saga/gfx.h" #include "saga/animation.h" diff --git a/saga/image.cpp b/saga/image.cpp index 7c98facc9c..d87a0e7f4f 100644 --- a/saga/image.cpp +++ b/saga/image.cpp @@ -27,6 +27,7 @@ #include "saga/game_mod.h" #include "saga/image.h" +#include "saga/stream.h" namespace Saga { @@ -64,13 +65,13 @@ int SagaEngine::decodeBGImage(const byte *image_data, size_t image_size, return FAILURE; } - MemoryReadStream readS(image_data, image_size); + MemoryReadStreamEndian readS(image_data, image_size, IS_BIG_ENDIAN); - hdr.width = readS.readUint16LE(); - hdr.height = readS.readUint16LE(); + hdr.width = readS.readUint16(); + hdr.height = readS.readUint16(); // The next four bytes of the image header aren't used. - readS.readUint16LE(); - readS.readUint16LE(); + readS.readUint16(); + readS.readUint16(); RLE_data_ptr = image_data + SAGA_IMAGE_DATA_OFFSET; RLE_data_len = image_size - SAGA_IMAGE_DATA_OFFSET; diff --git a/saga/isomap.cpp b/saga/isomap.cpp index 8b8397812b..c8cc4cde81 100644 --- a/saga/isomap.cpp +++ b/saga/isomap.cpp @@ -28,6 +28,7 @@ #include "saga/gfx.h" #include "saga/isomap.h" +#include "saga/stream.h" namespace Saga { @@ -46,10 +47,10 @@ int IsoMap::loadTileset(const byte *tileres_p, size_t tileres_len) { assert((_init) && (!_tiles_loaded)); assert((tileres_p != NULL) && (tileres_len > 0)); - MemoryReadStream readS(tileres_p, tileres_len); + MemoryReadStreamEndian readS(tileres_p, tileres_len, IS_BIG_ENDIAN); - readS.readUint16LE(); // skip - first_entry.tile_offset = readS.readUint16LE(); + readS.readUint16(); // skip + first_entry.tile_offset = readS.readUint16(); _tile_ct = first_entry.tile_offset / SAGA_ISOTILE_ENTRY_LEN; @@ -63,9 +64,9 @@ int IsoMap::loadTileset(const byte *tileres_p, size_t tileres_len) { for (i = 0; i < _tile_ct; i++) { tile_tbl[i].tile_h = readS.readByte(); tile_tbl[i].mask_rule = readS.readByte(); - tile_tbl[i].tile_offset = readS.readUint16LE(); - tile_tbl[i].terrain_mask = readS.readSint16LE(); - tile_tbl[i].mask = readS.readSint16LE(); + tile_tbl[i].tile_offset = readS.readUint16(); + tile_tbl[i].terrain_mask = readS.readSint16(); + tile_tbl[i].mask = readS.readSint16(); } _tiles_loaded = 1; @@ -85,7 +86,7 @@ int IsoMap::loadMetaTileset(const byte *mtileres_p, size_t mtileres_len) { assert(_init); assert((mtileres_p != NULL) && (mtileres_len > 0)); - MemoryReadStream readS(mtileres_p, mtileres_len); + MemoryReadStreamEndian readS(mtileres_p, mtileres_len, IS_BIG_ENDIAN); mtile_ct = mtileres_len / SAGA_METATILE_ENTRY_LEN; mtile_tbl = (ISO_METATILE_ENTRY *)malloc(mtile_ct * sizeof *mtile_tbl); @@ -94,13 +95,13 @@ int IsoMap::loadMetaTileset(const byte *mtileres_p, size_t mtileres_len) { } for (ct = 0; ct < mtile_ct; ct++) { - mtile_tbl[ct].mtile_n = readS.readUint16LE(); - mtile_tbl[ct].height = readS.readSint16LE(); - mtile_tbl[ct].highest_pixel = readS.readSint16LE(); + mtile_tbl[ct].mtile_n = readS.readUint16(); + mtile_tbl[ct].height = readS.readSint16(); + mtile_tbl[ct].highest_pixel = readS.readSint16(); mtile_tbl[ct].v_bits = readS.readByte(); mtile_tbl[ct].u_bits = readS.readByte(); for (i = 0; i < SAGA_METATILE_SIZE; i++) { - mtile_tbl[ct].tile_tbl[i] = readS.readUint16LE(); + mtile_tbl[ct].tile_tbl[i] = readS.readUint16(); } } @@ -117,11 +118,11 @@ int IsoMap::loadMetaTileset(const byte *mtileres_p, size_t mtileres_len) { int IsoMap::loadMetamap(const byte *mm_res_p, size_t mm_res_len) { int i; - MemoryReadStream readS(mm_res_p, mm_res_len); - _metamap_n = readS.readSint16LE(); + MemoryReadStreamEndian readS(mm_res_p, mm_res_len, IS_BIG_ENDIAN); + _metamap_n = readS.readSint16(); for (i = 0; i < SAGA_METAMAP_SIZE; i++) { - _metamap_tbl[i] = readS.readUint16LE(); + _metamap_tbl[i] = readS.readUint16(); } _mm_res_p = mm_res_p; diff --git a/saga/ite_introproc.cpp b/saga/ite_introproc.cpp index 7050a4b196..9318b977a2 100644 --- a/saga/ite_introproc.cpp +++ b/saga/ite_introproc.cpp @@ -26,7 +26,6 @@ #include "saga/saga.h" #include "saga/gfx.h" -#include "saga/yslib.h" #include "saga/animation.h" #include "saga/events.h" @@ -129,6 +128,7 @@ int Scene::ITEStartProc() { SCENE_QUEUE first_scene; GAME_SCENEDESC gs_desc; + int game_id = GAME_GetGame(); n_introscenes = ARRAYSIZE(ITE_IntroList); for (i = 0; i < n_introscenes; i++) { diff --git a/saga/list.h b/saga/list.h new file mode 100644 index 0000000000..dbffc4176c --- /dev/null +++ b/saga/list.h @@ -0,0 +1,154 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 The ScummVM project + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#ifndef SAGA_LIST_H__ +#define SAGA_LIST_H__ + +#include "common/list.h" + +namespace Saga { + + +template +class SortedList : public Common::List { +public: + typedef int ( CompareFunction ) (const T& , const T&); + + typedef typename Common::List::iterator iterator; + typedef typename Common::List::const_iterator const_iterator; + +public: + + iterator pushFront(const T& element) { + return insert(begin(), element); + } + + iterator pushBack(const T& element) { + return insert(end(), element); + } + + iterator insert(iterator pos, const T& element) { + Common::List::insert(pos, element); + return --pos; + } + + iterator pushFront() { + return insert(begin()); + } + + iterator pushBack() { + return insert(end()); + } + + iterator insert(iterator pos) { + T init; + return insert(pos, init); + } + + iterator pushFront(const T& element, CompareFunction* compareFunction) { + return insert(begin(), element, compareFunction); + } + + iterator pushBack(const T& element, CompareFunction* compareFunction) { + return insert(end(), element, compareFunction); + } + + iterator insert(iterator pos, const T& element, CompareFunction* compareFunction) { + int res; + + for (iterator i = begin(); i != end(); ++i) { + res = compareFunction(element, i.operator*()); + if (res < 0) { + return insert(i, element); + } + } + return pushBack(element); + } + + void reorderUp(iterator pos, CompareFunction* compareFunction) { + iterator i(pos); + int res; + + --i; + while (i != end()) { + res = compareFunction(i.operator*(), pos.operator*()); + if (res <= 0) { + + T temp(*pos); + erase(pos); + ++i; + Common::List::insert(i, temp); + return; + } + --i; + } + } + + void reorderDown(iterator pos, CompareFunction* compareFunction) { + iterator i(pos); + int res; + + ++i; + while (i != end()) { + res = compareFunction(i.operator*(), pos.operator*()); + if (res >= 0) { + + T temp(*pos); + erase(pos); + Common::List::insert(i, temp); + return; + } + ++i; + } + } + + iterator eraseAndPrev(iterator pos) { + assert(pos != end()); + iterator res(pos); + + --res; + erase(pos); + return res; + } + + void remove(const T* val) { + for (iterator i = begin(); i != end(); ++i) + if(val == i.operator->()) { + erase(i); + return; + } + } + + bool locate(const T* val, iterator& foundedIterator) { + + for (iterator i = begin(); i != end(); ++i) + if (val == i.operator->()) + { + foundedIterator = i; + return true; + } + + return false; + } +}; + +} // End of namespace Saga +#endif diff --git a/saga/music.cpp b/saga/music.cpp index da4dce3681..dd10297b2c 100644 --- a/saga/music.cpp +++ b/saga/music.cpp @@ -25,6 +25,7 @@ #include "saga/music.h" #include "saga/rscfile_mod.h" #include "saga/game_mod.h" +#include "saga/stream.h" #include "sound/audiostream.h" #include "sound/mididrv.h" #include "sound/midiparser.h" @@ -123,6 +124,7 @@ void RAWInputStream::refill() { uint32 len_left; byte *ptr = (byte *) _buf; + _file->seek(_file_pos, SEEK_SET); @@ -137,6 +139,12 @@ void RAWInputStream::refill() { if (len & 1) len--; + if (GAME_GetFeatures() & GF_BIG_ENDIAN_DATA) { + uint16 *ptr16 = (uint16 *)ptr; + for (uint32 i = 0; i < (len / 2); i++) + ptr16[i] = TO_BE_16(ptr16[i]); + } + len_left -= len; ptr += len; @@ -292,6 +300,7 @@ Music::Music(SoundMixer *mixer, MidiDriver *driver, int enabled) : _mixer(mixer) if (GAME_GetGameType() == GID_ITE) { File file; + byte footerBuf[ARRAYSIZE(_digiTableITECD) * 8]; // The lookup table is stored at the end of music.rsc. I don't // know why it has 27 elements, but the last one represents a @@ -312,11 +321,17 @@ Music::Music(SoundMixer *mixer, MidiDriver *driver, int enabled) : _mixer(mixer) _musicFname = RSC_FileName(_musicContext); file.open(_musicFname); + assert(file.size() > sizeof(footerBuf)); + file.seek(-ARRAYSIZE(_digiTableITECD) * 8, SEEK_END); + file.read(footerBuf, sizeof(footerBuf)); + + MemoryReadStreamEndian readS(footerBuf, sizeof(footerBuf), IS_BIG_ENDIAN); + for (int i = 0; i < ARRAYSIZE(_digiTableITECD); i++) { - _digiTableITECD[i].start = file.readUint32LE(); - _digiTableITECD[i].length = file.readUint32LE(); + _digiTableITECD[i].start = readS.readUint32(); + _digiTableITECD[i].length = readS.readUint32(); } file.close(); @@ -478,7 +493,7 @@ int Music::play(uint32 music_rn, uint16 flags) { } if (RSC_LoadResource(rsc_ctxt, music_rn, &resource_data, - &resource_size) != SUCCESS ) { + &resource_size) != SUCCESS) { warning("Music::play(): Resource load failed: %u", music_rn); return FAILURE; } diff --git a/saga/objectmap.cpp b/saga/objectmap.cpp index c5fe9782d7..b5d1e3102c 100644 --- a/saga/objectmap.cpp +++ b/saga/objectmap.cpp @@ -32,6 +32,8 @@ #include "saga/console.h" #include "saga/font.h" #include "saga/objectmap.h" +#include "saga/game_mod.h" +#include "saga/stream.h" namespace Saga { @@ -56,14 +58,14 @@ int ObjectMap::load(const byte *om_res, size_t om_res_len) { int i, k, m; - MemoryReadStream readS(om_res, om_res_len); + MemoryReadStreamEndian readS(om_res, om_res_len, IS_BIG_ENDIAN); if (_objectsLoaded) { freeMem(); } // Obtain object count N and allocate space for N objects - _nObjects = readS.readUint16LE(); + _nObjects = readS.readUint16(); _objectMaps = (OBJECTMAP_ENTRY *)malloc(_nObjects * sizeof *_objectMaps); @@ -79,8 +81,8 @@ int ObjectMap::load(const byte *om_res, size_t om_res_len) { object_map->nClickareas = readS.readByte(); object_map->defaultVerb = readS.readByte(); readS.readByte(); - object_map->objectNum = readS.readUint16LE(); - object_map->scriptNum = readS.readUint16LE(); + object_map->objectNum = readS.readUint16(); + object_map->scriptNum = readS.readUint16(); object_map->clickareas = (CLICKAREA *)malloc(object_map->nClickareas * sizeof *(object_map->clickareas)); if (object_map->clickareas == NULL) { @@ -103,8 +105,8 @@ int ObjectMap::load(const byte *om_res, size_t om_res_len) { // Load all points for this clickarea for (m = 0; m < clickarea->n_points; m++) { point = &clickarea->points[m]; - point->x = readS.readSint16LE(); - point->y = readS.readSint16LE(); + point->x = readS.readSint16(); + point->y = readS.readSint16(); } debug(2, "ObjectMap::load(): Read %d points for clickarea %d in object %d.", clickarea->n_points, k, object_map->objectNum); @@ -153,13 +155,13 @@ int ObjectMap::loadNames(const unsigned char *onl_res, size_t onl_res_len) { int i; - MemoryReadStream readS(onl_res, onl_res_len); + MemoryReadStreamEndian readS(onl_res, onl_res_len, IS_BIG_ENDIAN); if (_namesLoaded) { freeNames(); } - table_len = readS.readUint16LE(); + table_len = readS.readUint16(); n_names = table_len / 2 - 2; _nNames = n_names; @@ -173,7 +175,7 @@ int ObjectMap::loadNames(const unsigned char *onl_res, size_t onl_res_len) { } for (i = 0; i < n_names; i++) { - name_offset = readS.readUint16LE(); + name_offset = readS.readUint16(); _names[i] = (const char *)(onl_res + name_offset); debug(3, "Loaded object name string: %s", _names[i]); diff --git a/saga/palanim.cpp b/saga/palanim.cpp index fb15019af4..3bb3ca6506 100644 --- a/saga/palanim.cpp +++ b/saga/palanim.cpp @@ -29,6 +29,7 @@ #include "saga/game_mod.h" #include "saga/palanim.h" +#include "saga/stream.h" namespace Saga { @@ -54,13 +55,13 @@ int PalAnim::loadPalAnim(const byte *resdata, size_t resdata_len) { return FAILURE; } - MemoryReadStream readS(resdata, resdata_len); + MemoryReadStreamEndian readS(resdata, resdata_len, IS_BIG_ENDIAN); if (GAME_GetGameType() == GID_IHNM) { return SUCCESS; } - _entryCount = readS.readUint16LE(); + _entryCount = readS.readUint16(); debug(0, "PalAnim::loadPalAnim(): Loading %d PALANIM entries.", _entryCount); @@ -77,8 +78,8 @@ int PalAnim::loadPalAnim(const byte *resdata, size_t resdata_len) { int pal_count; int p, c; - color_count = readS.readUint16LE(); - pal_count = readS.readUint16LE(); + color_count = readS.readUint16(); + pal_count = readS.readUint16(); _entries[i].pal_count = pal_count; _entries[i].color_count = color_count; diff --git a/saga/resnames.h b/saga/resnames.h index fb4bc0f3d3..ea9f0f07e4 100644 --- a/saga/resnames.h +++ b/saga/resnames.h @@ -29,6 +29,7 @@ namespace Saga { // Lookup tables +#define ITEMACDEMO_SCENE_LUT 1804 #define ITE_SCENE_LUT 1806 #define ITE_SCRIPT_LUT 216 @@ -57,6 +58,7 @@ namespace Saga { #define ITE_DEFAULT_PORTRAITS 125 // ITE Scene resource numbers +#define ITEMACDEMO_INTRO_ANIM_SCENE 1536 #define ITE_INTRO_ANIM_SCENE 1538 #define ITE_CAVE_SCENE_1 1542 #define ITE_CAVE_SCENE_2 1545 diff --git a/saga/rscfile.cpp b/saga/rscfile.cpp index 929c1c5f6e..cbfa60b484 100644 --- a/saga/rscfile.cpp +++ b/saga/rscfile.cpp @@ -26,6 +26,8 @@ #include "saga/rscfile_mod.h" #include "saga/rscfile.h" +#include "saga/game_mod.h" +#include "saga/stream.h" namespace Saga { @@ -113,11 +115,11 @@ int RSC_LoadRSC(RSCFILE_CONTEXT *rsc) { if (rsc->rc_file->read(tblinfo_buf, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) { return FAILURE; } + + MemoryReadStreamEndian readS(tblinfo_buf, RSC_TABLEINFO_SIZE, IS_BIG_ENDIAN); - MemoryReadStream readS(tblinfo_buf, RSC_TABLEINFO_SIZE); - - res_tbl_offset = readS.readUint32LE(); - res_tbl_ct = readS.readUint32LE(); + res_tbl_offset = readS.readUint32(); + res_tbl_ct = readS.readUint32(); // Check for sane table offset if (res_tbl_offset != rsc->rc_file->size() - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * res_tbl_ct) { @@ -146,11 +148,13 @@ int RSC_LoadRSC(RSCFILE_CONTEXT *rsc) { return FAILURE; } - MemoryReadStream readS1(tbl_buf, tbl_len); + MemoryReadStreamEndian readS1(tbl_buf, tbl_len, IS_BIG_ENDIAN); + debug(9, "RSC %s", rsc->rc_file_fspec); for (i = 0; i < res_tbl_ct; i++) { - rsc_restbl[i].res_offset = readS1.readUint32LE(); - rsc_restbl[i].res_size = readS1.readUint32LE(); + rsc_restbl[i].res_offset = readS1.readUint32(); + rsc_restbl[i].res_size = readS1.readUint32(); + //debug(9, "#%x Offset:%x Size:%x", i, rsc_restbl[i].res_offset, rsc_restbl[i].res_size); if ((rsc_restbl[i].res_offset > rsc->rc_file->size()) || (rsc_restbl[i].res_size > rsc->rc_file->size())) { free(tbl_buf); free(rsc_restbl); @@ -258,4 +262,18 @@ int RSC_FreeResource(byte *resource_ptr) { return SUCCESS; } +int RSC_ConvertID(int id) { + int res = id; + + if (IS_MAC_VERSION) { + if (res > 1537) + res -= 2; + else if (res == 1535 || res == 1536) { + error ("Wrong resource number %d for Mac ITE"); + } + } + + return res; +} + } // End of namespace Saga diff --git a/saga/rscfile_mod.h b/saga/rscfile_mod.h index 4bcf7ce32c..b8c3f88fc2 100644 --- a/saga/rscfile_mod.h +++ b/saga/rscfile_mod.h @@ -40,6 +40,7 @@ int RSC_GetResourceOffset(RSCFILE_CONTEXT *, uint32, uint32 *); int RSC_LoadResource(RSCFILE_CONTEXT *, uint32, byte **, size_t *); int RSC_FreeResource(byte *); const char *RSC_FileName(RSCFILE_CONTEXT *rsc); +int RSC_ConvertID(int id); } // End of namespace Saga diff --git a/saga/saga.h b/saga/saga.h index 7a7abe765b..04b301eaba 100644 --- a/saga/saga.h +++ b/saga/saga.h @@ -58,7 +58,6 @@ class Console; class Events; class PalAnim; -using Common::MemoryReadStream; #define PBOUNDS(n,max) (((n)>=(0))&&((n)<(max))) #define MAXPATH 512 diff --git a/saga/scene.cpp b/saga/scene.cpp index b001752730..6b81fa16fe 100644 --- a/saga/scene.cpp +++ b/saga/scene.cpp @@ -23,7 +23,6 @@ // Scene management module #include "saga/saga.h" -#include "saga/yslib.h" #include "saga/gfx.h" #include "saga/game_mod.h" @@ -43,6 +42,7 @@ #include "saga/music.h" #include "saga/scene.h" +#include "saga/stream.h" namespace Saga { @@ -63,11 +63,6 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) { return; } - // Initialize scene queue - _sceneQueue = ys_dll_create(); - if (_sceneQueue == NULL) { - return; - } // Load scene lookup table debug(0, "Loading scene LUT from resource %u.", gs_desc.scene_lut_rn); @@ -76,7 +71,10 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) { warning("Scene::Scene(): Error: couldn't load scene LUT"); return; } - + if (scene_lut_len==0) { + warning("Scene::Scene(): scene_lut_len==0"); + return; + } _sceneCount = scene_lut_len / 2; _sceneMax = _sceneCount - 1; _sceneLUT = (int *)malloc(_sceneMax * sizeof *_sceneLUT); @@ -85,10 +83,10 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) { return; } - MemoryReadStream readS(scene_lut_p, scene_lut_len); + MemoryReadStreamEndian readS(scene_lut_p, scene_lut_len, IS_BIG_ENDIAN); for (i = 0; i < _sceneMax; i++) { - _sceneLUT[i] = readS.readUint16LE(); + _sceneLUT[i] = readS.readUint16(); } free(scene_lut_p); @@ -119,7 +117,6 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) { _resListEntries = 0; _resList = NULL; _animEntries = 0; - _animList = NULL; _sceneProc = NULL; _objectMap = NULL; _actionMap = NULL; @@ -140,21 +137,20 @@ int Scene::queueScene(SCENE_QUEUE *scene_queue) { assert(_initialized); assert(scene_queue != NULL); - ys_dll_add_tail(_sceneQueue, scene_queue, sizeof *scene_queue); - + _sceneQueue.push_back(*scene_queue); return SUCCESS; } int Scene::clearSceneQueue() { assert(_initialized); - ys_dll_delete_all(_sceneQueue); + _sceneQueue.clear(); return SUCCESS; } int Scene::startScene() { - YS_DL_NODE *node; + SceneQueueList::iterator queueIterator; SCENE_QUEUE *scene_qdat; EVENT event; @@ -188,13 +184,13 @@ int Scene::startScene() { break; } - // Load the head node in scene queue - node = ys_dll_head(_sceneQueue); - if (node == NULL) { + // Load the head in scene queue + queueIterator = _sceneQueue.begin(); + if (queueIterator == _sceneQueue.end()) { return SUCCESS; } - scene_qdat = (SCENE_QUEUE *)ys_dll_get_data(node); + scene_qdat = queueIterator.operator->(); assert(scene_qdat != NULL); loadScene(scene_qdat->scene_n, scene_qdat->load_flag, scene_qdat->scene_proc, scene_qdat->scene_desc, scene_qdat->fadeType); @@ -203,7 +199,7 @@ int Scene::startScene() { } int Scene::nextScene() { - YS_DL_NODE *node; + SceneQueueList::iterator queueIterator; SCENE_QUEUE *scene_qdat; assert(_initialized); @@ -220,32 +216,29 @@ int Scene::nextScene() { endScene(); - // Delete the current head node in scene queue - node = ys_dll_head(_sceneQueue); - if (node == NULL) { + // Delete the current head in scene queue + queueIterator = _sceneQueue.begin(); + if (queueIterator == _sceneQueue.end()) { return SUCCESS; } + + queueIterator = _sceneQueue.erase(queueIterator); - ys_dll_delete(node); - - // Load the head node in scene queue - node = ys_dll_head(_sceneQueue); - if (node == NULL) { + if (queueIterator == _sceneQueue.end()) { return SUCCESS; } - scene_qdat = (SCENE_QUEUE *)ys_dll_get_data(node); + // Load the head in scene queue + scene_qdat = queueIterator.operator->(); assert(scene_qdat != NULL); - loadScene(scene_qdat->scene_n, scene_qdat->load_flag, scene_qdat->scene_proc, scene_qdat->scene_desc, scene_qdat->fadeType); + loadScene(RSC_ConvertID(scene_qdat->scene_n), scene_qdat->load_flag, scene_qdat->scene_proc, scene_qdat->scene_desc, scene_qdat->fadeType); return SUCCESS; } int Scene::skipScene() { - YS_DL_NODE *node; - YS_DL_NODE *prev_node; - YS_DL_NODE *skip_node = NULL; + SceneQueueList::iterator queueIterator; SCENE_QUEUE *scene_qdat = NULL; SCENE_QUEUE *skip_qdat = NULL; @@ -263,29 +256,28 @@ int Scene::skipScene() { } // Walk down scene queue and try to find a skip target - node = ys_dll_head(_sceneQueue); - if (node == NULL) { + queueIterator = _sceneQueue.begin(); + if (queueIterator == _sceneQueue.end()) { warning("Scene::skip(): Error: Can't skip scene...no scenes in queue"); return FAILURE; } - for (node = ys_dll_next(node); node != NULL; node = ys_dll_next(node)) { - scene_qdat = (SCENE_QUEUE *)ys_dll_get_data(node); + ++queueIterator; + while (queueIterator != _sceneQueue.end()) { + scene_qdat = queueIterator.operator->(); assert(scene_qdat != NULL); if (scene_qdat->scene_skiptarget) { - skip_node = node; skip_qdat = scene_qdat; break; } + ++queueIterator; } // If skip target found, remove preceding scenes and load - if (skip_node != NULL) { - for (node = ys_dll_prev(skip_node); node != NULL; node = prev_node) { - prev_node = ys_dll_prev(node); - ys_dll_delete(node); - } + if (skip_qdat != NULL) { + _sceneQueue.erase(_sceneQueue.begin(), queueIterator); + endScene(); loadScene(skip_qdat->scene_n, skip_qdat->load_flag, skip_qdat->scene_proc, skip_qdat->scene_desc, skip_qdat->fadeType); } @@ -419,7 +411,6 @@ int Scene::loadScene(int scene_num, int load_flag, SCENE_PROC scene_proc, SCENE_ return FAILURE; } - _animList = ys_dll_create(); _sceneMode = 0; _loadDesc = true; @@ -576,21 +567,16 @@ int Scene::loadSceneDescriptor(uint32 res_number) { return FAILURE; } - if (scene_desc_len != SAGA_SCENE_DESC_LEN) { - warning("Scene::loadSceneDescriptor(): Error: scene descriptor length invalid"); - return FAILURE; - } - - MemoryReadStream readS(scene_desc_data, scene_desc_len); + MemoryReadStreamEndian readS(scene_desc_data, scene_desc_len, IS_BIG_ENDIAN); - _desc.flags = readS.readSint16LE(); - _desc.resListRN = readS.readSint16LE(); - _desc.endSlope = readS.readSint16LE(); - _desc.beginSlope = readS.readSint16LE(); - _desc.scriptNum = readS.readUint16LE(); - _desc.sceneScriptNum = readS.readUint16LE(); - _desc.startScriptNum = readS.readUint16LE(); - _desc.musicRN = readS.readSint16LE(); + _desc.flags = readS.readSint16(); + _desc.resListRN = readS.readSint16(); + _desc.endSlope = readS.readSint16(); + _desc.beginSlope = readS.readSint16(); + _desc.scriptNum = readS.readUint16(); + _desc.sceneScriptNum = readS.readUint16(); + _desc.startScriptNum = readS.readUint16(); + _desc.musicRN = readS.readSint16(); RSC_FreeResource(scene_desc_data); @@ -610,7 +596,7 @@ int Scene::loadSceneResourceList(uint32 reslist_rn) { return FAILURE; } - MemoryReadStream readS(resource_list, resource_list_len); + MemoryReadStreamEndian readS(resource_list, resource_list_len, IS_BIG_ENDIAN); // Allocate memory for scene resource list _resListEntries = resource_list_len / SAGA_RESLIST_ENTRY_LEN; @@ -627,8 +613,8 @@ int Scene::loadSceneResourceList(uint32 reslist_rn) { debug(0, "Loading scene resource list..."); for (i = 0; i < _resListEntries; i++) { - _resList[i].res_number = readS.readUint16LE(); - _resList[i].res_type = readS.readUint16LE(); + _resList[i].res_number = readS.readUint16(); + _resList[i].res_type = readS.readUint16(); } RSC_FreeResource(resource_list); @@ -754,26 +740,22 @@ int Scene::processSceneResources() { case SAGA_ANIM_6: case SAGA_ANIM_7: { - SCENE_ANIMINFO *new_animinfo; uint16 new_anim_id; debug(0, "Loading animation resource..."); - new_animinfo = (SCENE_ANIMINFO *)malloc(sizeof *new_animinfo); - if (new_animinfo == NULL) { - warning("Scene::ProcessSceneResources(): Memory allocation error"); - return MEM; - } - if (_vm->_anim->load(_resList[i].res_data, _resList[i].res_data_len, &new_anim_id) != SUCCESS) { warning("Scene::ProcessSceneResources(): Error loading animation resource"); return FAILURE; } + SCENE_ANIMINFO *new_animinfo; + + new_animinfo = _animList.pushBack().operator->(); + new_animinfo->anim_handle = new_anim_id; new_animinfo->anim_res_number = _resList[i].res_number; - ys_dll_add_tail(_animList, new_animinfo, sizeof *new_animinfo); _animEntries++; } break; @@ -874,7 +856,7 @@ int Scene::endScene() { _objectMap = NULL; _actionMap = NULL; - ys_dll_destroy(_animList); + _animList.clear(); _animEntries = 0; diff --git a/saga/scene.h b/saga/scene.h index b4124573a4..3f821e460f 100644 --- a/saga/scene.h +++ b/saga/scene.h @@ -27,6 +27,7 @@ #define SAGA_SCENE_H #include "saga/text.h" +#include "saga/list.h" namespace Saga { @@ -136,9 +137,11 @@ struct SCENE_IMAGE { struct SCENE_ANIMINFO { int anim_res_number; int anim_handle; - SCENE_ANIMINFO *next; + //SCENE_ANIMINFO *next; }; +typedef SortedList SceneAnimInfoList; + enum SCENE_FADE_TYPES { SCENE_NOFADE = 0, SCENE_FADE = 1, @@ -154,6 +157,8 @@ struct SCENE_QUEUE { int fadeType; }; +typedef Common::List SceneQueueList; + ///// IHNM-specific stuff #define IHNM_PALFADE_TIME 1000 #define IHNM_INTRO_FRAMETIME 80 @@ -258,7 +263,7 @@ class Scene { int *_sceneLUT; int _sceneCount; int _sceneMax; - YS_DL_LIST *_sceneQueue; + SceneQueueList _sceneQueue; int _firstScene; bool _sceneLoaded; int _sceneMode; @@ -270,7 +275,7 @@ class Scene { int _resListEntries; SCENE_RESLIST *_resList; int _animEntries; - YS_DL_LIST *_animList; + SceneAnimInfoList _animList; SCENE_PROC *_sceneProc; TEXTLIST *_textList; SCENE_IMAGE _bg; diff --git a/saga/script.cpp b/saga/script.cpp index 228b8f2191..fe4efa1fe4 100644 --- a/saga/script.cpp +++ b/saga/script.cpp @@ -23,7 +23,6 @@ // Scripting module: Script resource handling functions #include "saga/saga.h" -#include "saga/yslib.h" #include "saga/gfx.h" #include "saga/rscfile_mod.h" @@ -31,6 +30,7 @@ #include "saga/console.h" #include "saga/script.h" +#include "saga/stream.h" namespace Saga { @@ -51,7 +51,6 @@ Script::Script() { _voiceLUTPresent = false; _scriptLUTEntryLen = 0; _currentScript = 0; - _threadList = 0; _abortEnabled = true; _skipSpeeches = false; memset(_dataBuf, 0, sizeof(_dataBuf)); @@ -98,12 +97,12 @@ Script::Script() { } // Convert LUT resource to logical LUT - MemoryReadStream scriptS(rsc_ptr, rsc_len); + MemoryReadStreamEndian scriptS(rsc_ptr, rsc_len, IS_BIG_ENDIAN); for (i = 0; i < _scriptLUTMax; i++) { prevTell = scriptS.pos(); - _scriptLUT[i].script_rn = scriptS.readUint16LE(); - _scriptLUT[i].diag_list_rn = scriptS.readUint16LE(); - _scriptLUT[i].voice_lut_rn = scriptS.readUint16LE(); + _scriptLUT[i].script_rn = scriptS.readUint16(); + _scriptLUT[i].diag_list_rn = scriptS.readUint16(); + _scriptLUT[i].voice_lut_rn = scriptS.readUint16(); // Skip the unused portion of the structure for (j = scriptS.pos(); j < prevTell + _scriptLUTEntryLen; j++) { @@ -122,8 +121,6 @@ Script::Script() { } } - // Initialize script submodules - _threadList = ys_dll_create(); setupScriptFuncList(); @@ -132,8 +129,6 @@ Script::Script() { // Shut down script module gracefully; free all allocated module resources Script::~Script() { - YS_DL_NODE *thread_node; - SCRIPT_THREAD *thread; if (!_initialized) { error("Script not initialized"); @@ -143,15 +138,7 @@ Script::~Script() { // Free script lookup table free(_scriptLUT); - - // Stop all threads and destroy them - - for (thread_node = ys_dll_head(_threadList); thread_node != NULL; - thread_node = ys_dll_next(thread_node)) { - thread = (SCRIPT_THREAD *)ys_dll_get_data(thread_node); - SThreadDestroy(thread); - } - + _initialized = false; } @@ -322,12 +309,14 @@ SCRIPT_BYTECODE *Script::loadBytecode(byte *bytecode_p, size_t bytecode_len) { debug(0, "Loading script bytecode..."); - MemoryReadStream scriptS(bytecode_p, bytecode_len); + MemoryReadStreamEndian scriptS(bytecode_p, bytecode_len, IS_BIG_ENDIAN); // The first two uint32 values are the number of entrypoints, and the // offset to the entrypoint table, respectively. - n_entrypoints = scriptS.readUint32LE(); - ep_tbl_offset = scriptS.readUint32LE(); + n_entrypoints = scriptS.readUint16(); + scriptS.readUint16(); //skip + ep_tbl_offset = scriptS.readUint16(); + scriptS.readUint16(); //skip // Check that the entrypoint table offset is valid. if ((bytecode_len - ep_tbl_offset) < (n_entrypoints * SCRIPT_TBLENTRY_LEN)) { @@ -365,8 +354,8 @@ SCRIPT_BYTECODE *Script::loadBytecode(byte *bytecode_p, size_t bytecode_len) { // First uint16 is the offset of the entrypoint name from the start // of the bytecode resource, second uint16 is the offset of the // bytecode itself for said entrypoint - bc_ep_tbl[i].name_offset = scriptS.readUint16LE(); - bc_ep_tbl[i].offset = scriptS.readUint16LE(); + bc_ep_tbl[i].name_offset = scriptS.readUint16(); + bc_ep_tbl[i].offset = scriptS.readUint16(); // Perform a simple range check on offset values if ((bc_ep_tbl[i].name_offset > bytecode_len) || (bc_ep_tbl[i].offset > bytecode_len)) { @@ -403,10 +392,10 @@ DIALOGUE_LIST *Script::loadDialogue(const byte *dialogue_p, size_t dialogue_len) return NULL; } - MemoryReadStream scriptS(dialogue_p, dialogue_len); + MemoryReadStreamEndian scriptS(dialogue_p, dialogue_len, IS_BIG_ENDIAN); // First uint16 is the offset of the first string - offset = scriptS.readUint16LE(); + offset = scriptS.readUint16(); if (offset > dialogue_len) { warning("Error, invalid string offset"); return NULL; @@ -434,7 +423,7 @@ DIALOGUE_LIST *Script::loadDialogue(const byte *dialogue_p, size_t dialogue_len) // Read in tables from dialogue list resource scriptS.seek(0); for (i = 0; i < n_dialogue; i++) { - offset = scriptS.readUint16LE(); + offset = scriptS.readUint16(); if (offset > dialogue_len) { warning("Error, invalid string offset"); free(dialogue_list->str); @@ -474,10 +463,10 @@ VOICE_LUT *Script::loadVoiceLUT(const byte *voicelut_p, size_t voicelut_len, SCR return NULL; } - MemoryReadStream scriptS(voicelut_p, voicelut_len); + MemoryReadStreamEndian scriptS(voicelut_p, voicelut_len, IS_BIG_ENDIAN); for (i = 0; i < n_voices; i++) { - voice_lut->voices[i] = scriptS.readUint16LE(); + voice_lut->voices[i] = scriptS.readUint16(); } return voice_lut; diff --git a/saga/script.h b/saga/script.h index 6777393c55..2e36dd87cb 100644 --- a/saga/script.h +++ b/saga/script.h @@ -27,7 +27,7 @@ #define SAGA_SCRIPT_H #include "saga/text.h" -#include "saga/yslib.h" +#include "saga/list.h" namespace Saga { @@ -135,8 +135,12 @@ struct SCRIPT_THREAD { assert(stackPtr < ARRAYSIZE(stackBuf)); return stackBuf[stackPtr++]; } + + SCRIPT_THREAD() { memset(this, 0, sizeof(*this)); } }; +typedef SortedList ScriptThreadList; + struct PROC_TBLENTRY { size_t name_offset; size_t offset; @@ -200,7 +204,7 @@ public: SCRIPTDATA *currentScript() { return _currentScript; } void setBuffer(int idx, SCRIPT_DATABUF *ptr) { _dataBuf[idx] = ptr; } SCRIPT_DATABUF *dataBuffer(int idx) { return _dataBuf[idx]; } - YS_DL_LIST *threadList() { return _threadList; } +// YS_DL_LIST *threadList() { return _threadList; } void scriptInfo(); void scriptExec(int argc, const char **argv); @@ -214,7 +218,7 @@ protected: uint16 _scriptLUTEntryLen; SCRIPTDATA *_currentScript; SCRIPT_DATABUF *_dataBuf[SCRIPT_DATABUF_NUM]; - YS_DL_LIST *_threadList; + ScriptThreadList _threadList; bool _skipSpeeches; bool _abortEnabled; diff --git a/saga/sdebug.cpp b/saga/sdebug.cpp index 2064533758..51ddab4305 100644 --- a/saga/sdebug.cpp +++ b/saga/sdebug.cpp @@ -30,11 +30,13 @@ #include "saga/font.h" #include "saga/script.h" +#include "saga/game_mod.h" +#include "saga/stream.h" namespace Saga { #define SD_DISPLAY_LEN 128 -#define SD_ADDTXT( x ) strncat( disp_buf, x, SD_DISPLAY_LEN ); +#define SD_ADDTXT(x) strncat(disp_buf, x, SD_DISPLAY_LEN); int Script::SDebugPrintInstr(SCRIPT_THREAD *thread) { TEXTLIST_ENTRY tl_e; @@ -64,10 +66,10 @@ int Script::SDebugPrintInstr(SCRIPT_THREAD *thread) { tl_e.string = disp_buf; tl_e.display = 1; - MemoryReadStream readS(currentScript()->bytecode->bytecode_p + MemoryReadStream/*Endian*/ readS(currentScript()->bytecode->bytecode_p + thread->i_offset, currentScript()->bytecode->bytecode_len - - thread->i_offset); + - thread->i_offset/*, IS_BIG_ENDIAN*/); in_char = readS.readByte(); sprintf(tmp_buf, "%04lX | %02X | ", thread->i_offset, in_char); strncat(disp_buf, tmp_buf, SD_DISPLAY_LEN); @@ -103,11 +105,11 @@ int Script::SDebugPrintInstr(SCRIPT_THREAD *thread) { sprintf(tmp_buf, "%02X", param); SD_ADDTXT(tmp_buf); /* - if(( param >= 0 ) && ( param < diag_list->n_dialogue )) { - debug(2, " ; \"%.*s\"", SCRIPT_STRINGLIMIT, diag_list->str[param] ); + if((param >= 0) && (param < diag_list->n_dialogue)) { + debug(2, " ; \"%.*s\"", SCRIPT_STRINGLIMIT, diag_list->str[param]); } else { - debug(2, " ; Invalid dialogue string.\n" ); + debug(2, " ; Invalid dialogue string.\n"); } */ } @@ -243,9 +245,9 @@ int Script::SDebugPrintInstr(SCRIPT_THREAD *thread) { sprintf(tmp_buf, "%04X ", param); SD_ADDTXT(tmp_buf); /* - for( i = 0 ; i < script_list->n_scripts ; i++ ) { - if( op_offset == script_list->scripts[i].offset ) { - debug(2, "; Entrypoint \"%s\".", script_list->scriptl_p + script_list->scripts[i].name_offset ); + for(i = 0 ; i < script_list->n_scripts ; i++) { + if(op_offset == script_list->scripts[i].offset) { + debug(2, "; Entrypoint \"%s\".", script_list->scriptl_p + script_list->scripts[i].name_offset); break; } } @@ -328,10 +330,10 @@ int Script::SDebugPrintInstr(SCRIPT_THREAD *thread) { for (i = 0; i < n_switch; i++) { switch_num = readS.readUint16LE(); switch_jmp = readS.readUint16LE(); - // printf( TAB "CASE %04X, %04X\n", switch_num, switch_jmp); + // printf(TAB "CASE %04X, %04X\n", switch_num, switch_jmp); } default_jmp = readS.readUint16LE(); - //printf( TAB "DEF %04X", default_jmp); + //printf(TAB "DEF %04X", default_jmp); } break; // Random branch diff --git a/saga/sndres.cpp b/saga/sndres.cpp index da94ec664e..38e1fdfcae 100644 --- a/saga/sndres.cpp +++ b/saga/sndres.cpp @@ -30,6 +30,7 @@ #include "saga/sndres.h" #include "saga/sound.h" +#include "saga/stream.h" #include "common/file.h" @@ -175,7 +176,7 @@ int SndRes::load(RSCFILE_CONTEXT *snd_ctxt, uint32 snd_rn, SOUNDBUFFER *snd_buf_ } int SndRes::loadVocSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf_i) { - MemoryReadStream readS(snd_res, snd_res_len); + MemoryReadStreamEndian readS(snd_res, snd_res_len, IS_BIG_ENDIAN); byte *data; int rate; int len; @@ -188,11 +189,11 @@ int SndRes::loadVocSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf snd_buf_i->s_freq = rate; snd_buf_i->s_samplebits = 8; - snd_buf_i->s_stereo = 0; + snd_buf_i->s_stereo = 0; snd_buf_i->s_signed = 0; snd_buf_i->s_buf = data; snd_buf_i->s_buf_len = len; - + return SUCCESS; } @@ -200,7 +201,7 @@ int SndRes::loadVocSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf int SndRes::loadWavSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf_i) { // TODO: This function should, perhaps, be made more robust. - MemoryReadStream readS(snd_res, snd_res_len); + MemoryReadStreamEndian readS(snd_res, snd_res_len, IS_BIG_ENDIAN); byte buf[4]; @@ -209,7 +210,7 @@ int SndRes::loadWavSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf return FAILURE; } - readS.readUint32LE(); + readS.readUint32(); readS.read(buf, sizeof(buf)); if (memcmp(buf, "WAVE", sizeof(buf)) != 0) { @@ -221,13 +222,13 @@ int SndRes::loadWavSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf return FAILURE; } - uint32 len = readS.readUint32LE(); + uint32 len = readS.readUint32(); uint32 pos = readS.pos(); - readS.readUint16LE(); + readS.readUint16(); - snd_buf_i->s_stereo = (readS.readUint16LE() == 2) ? 1 : 0; - snd_buf_i->s_freq = readS.readUint16LE(); + snd_buf_i->s_stereo = (readS.readUint16() == 2) ? 1 : 0; + snd_buf_i->s_freq = readS.readUint16(); snd_buf_i->s_samplebits = 16; snd_buf_i->s_signed = 1; @@ -239,11 +240,11 @@ int SndRes::loadWavSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf break; } - len = readS.readUint32LE(); + len = readS.readUint32(); readS.seek(len, SEEK_CUR); } - snd_buf_i->s_buf_len = readS.readUint32LE(); + snd_buf_i->s_buf_len = readS.readUint32(); byte *data = (byte *)malloc(snd_buf_i->s_buf_len); if (!data) { diff --git a/saga/sprite.cpp b/saga/sprite.cpp index 96631006e9..0e0645d2dc 100644 --- a/saga/sprite.cpp +++ b/saga/sprite.cpp @@ -33,6 +33,7 @@ #include "saga/font.h" #include "saga/sprite.h" +#include "saga/stream.h" namespace Saga { @@ -81,9 +82,9 @@ int Sprite::loadList(int resource_num, SPRITELIST **sprite_list_p) { return FAILURE; } - MemoryReadStream readS(spritelist_data, spritelist_len); + MemoryReadStreamEndian readS(spritelist_data, spritelist_len, IS_BIG_ENDIAN); - sprite_count = readS.readUint16LE(); + sprite_count = readS.readUint16(); new_slist->sprite_count = sprite_count; @@ -95,7 +96,7 @@ int Sprite::loadList(int resource_num, SPRITELIST **sprite_list_p) { for (i = 0; i < sprite_count; i++) { new_slist->offset_list[i].data_idx = 0; - new_slist->offset_list[i].offset = readS.readUint16LE(); + new_slist->offset_list[i].offset = readS.readUint16(); } new_slist->slist_rn = resource_num; @@ -124,9 +125,9 @@ int Sprite::appendList(int resource_num, SPRITELIST *spritelist) { return FAILURE; } - MemoryReadStream readS(spritelist_data, spritelist_len); + MemoryReadStreamEndian readS(spritelist_data, spritelist_len, IS_BIG_ENDIAN); - sprite_count = readS.readUint16LE(); + sprite_count = readS.readUint16(); old_sprite_count = spritelist->sprite_count; new_sprite_count = spritelist->sprite_count + sprite_count; @@ -143,7 +144,7 @@ int Sprite::appendList(int resource_num, SPRITELIST *spritelist) { for (i = old_sprite_count; i < spritelist->sprite_count; i++) { spritelist->offset_list[i].data_idx = spritelist->append_count; - spritelist->offset_list[i].offset = readS.readUint16LE(); + spritelist->offset_list[i].offset = readS.readUint16(); } spritelist->sprite_data[spritelist->append_count] = spritelist_data; @@ -194,7 +195,8 @@ int Sprite::draw(SURFACE *ds, SPRITELIST *sprite_list, int sprite_num, int spr_x sprite_p = sprite_list->sprite_data[offset_idx]; sprite_p += offset; - MemoryReadStream readS(sprite_p, 5); + assert(sprite_p); + MemoryReadStreamEndian readS(sprite_p, 5, IS_BIG_ENDIAN); x_align = readS.readSByte(); y_align = readS.readSByte(); @@ -302,7 +304,7 @@ int Sprite::drawOccluded(SURFACE *ds, SPRITELIST *sprite_list, int sprite_num, i sprite_p = sprite_list->sprite_data[offset_idx]; sprite_p += offset; - MemoryReadStream readS(sprite_p, 5); + MemoryReadStreamEndian readS(sprite_p, 5, IS_BIG_ENDIAN); // Read sprite dimensions -- should probably cache this stuff in // sprite list @@ -383,7 +385,7 @@ int Sprite::drawOccluded(SURFACE *ds, SPRITELIST *sprite_list, int sprite_num, i /* { char buf[1024] = { 0 }; - sprintf( buf, "dw: %d, dh: %d.", ci.draw_w, ci.draw_h ); + sprintf(buf, "dw: %d, dh: %d.", ci.draw_w, ci.draw_h); _vm->textDraw(2, ds, buf, spr_x - x_align, spr_y - y_align, 255, 0, FONT_OUTLINE); } diff --git a/saga/sthread.cpp b/saga/sthread.cpp index e6fed99bff..f50524f80d 100644 --- a/saga/sthread.cpp +++ b/saga/sthread.cpp @@ -23,7 +23,6 @@ // Scripting module thread management component #include "saga/saga.h" -#include "saga/yslib.h" #include "saga/gfx.h" #include "saga/actor.h" @@ -32,6 +31,8 @@ #include "saga/script.h" #include "saga/sdata.h" +#include "saga/game_mod.h" +#include "saga/stream.h" namespace Saga { @@ -42,22 +43,13 @@ void Script::setFramePtr(SCRIPT_THREAD *thread, int newPtr) { } SCRIPT_THREAD *Script::SThreadCreate() { - YS_DL_NODE *new_node; SCRIPT_THREAD *new_thread; if (!isInitialized()) { return NULL; } - new_thread = (SCRIPT_THREAD *)calloc(1, sizeof *new_thread); - if (new_thread == NULL) { - return NULL; - } - - new_node = ys_dll_add_head(threadList(), new_thread, sizeof *new_thread); - free(new_thread); - - new_thread = (SCRIPT_THREAD *)ys_dll_get_data(new_node); + new_thread = _threadList.pushFront().operator->(); new_thread->stackPtr = ARRAYSIZE(new_thread->stackBuf) - 1; setFramePtr(new_thread, new_thread->stackPtr); @@ -71,45 +63,24 @@ SCRIPT_THREAD *Script::SThreadCreate() { return new_thread; } -int Script::SThreadDestroy(SCRIPT_THREAD *thread) { - YS_DL_NODE *walk_p; - SCRIPT_THREAD *th; - - if (thread == NULL) { - return FAILURE; - } - - for (walk_p = ys_dll_head(threadList()); walk_p != NULL; walk_p = ys_dll_next(walk_p)) { - th = (SCRIPT_THREAD *)ys_dll_get_data(walk_p); - if (thread == th) { - ys_dll_delete(walk_p); - break; - } - } - - return SUCCESS; -} int Script::SThreadExecThreads(uint msec) { - YS_DL_NODE *walk_p, *next_p; SCRIPT_THREAD *thread; if (!isInitialized()) { return FAILURE; } - walk_p = ys_dll_head(threadList()); + ScriptThreadList::iterator threadi = _threadList.begin(); - while (walk_p != NULL) { - next_p = ys_dll_next(walk_p); - - thread = (SCRIPT_THREAD *)ys_dll_get_data(walk_p); + while (threadi != _threadList.end()) { + thread = (SCRIPT_THREAD *)threadi.operator->(); if (thread->flags & (kTFlagFinished | kTFlagAborted)) { //if (thread->flags & kTFlagFinished) // FIXME. Missing function - SThreadDestroy(thread); - walk_p = next_p; + + threadi = _threadList.erase(threadi); continue; } @@ -131,14 +102,14 @@ int Script::SThreadExecThreads(uint msec) { if (!(thread->flags & kTFlagWaiting)) SThreadRun(thread, STHREAD_TIMESLICE); - walk_p = next_p; + ++threadi; } return SUCCESS; } void Script::SThreadCompleteThread(void) { - for (int i = 0; i < 40 && (ys_dll_head(threadList()) != NULL); i++) + for (int i = 0; i < 40 && !_threadList.isEmpty() ; i++) SThreadExecThreads(0); } @@ -260,7 +231,7 @@ int Script::SThreadRun(SCRIPT_THREAD *thread, int instr_limit) { } } - MemoryReadStream scriptS(currentScript()->bytecode->bytecode_p, currentScript()->bytecode->bytecode_len); + MemoryReadStream/*Endian*/ scriptS(currentScript()->bytecode->bytecode_p, currentScript()->bytecode->bytecode_len/*, IS_BIG_ENDIAN*/); dataBuffer(2)->len = currentScript()->bytecode->bytecode_len / sizeof(SDataWord_T); dataBuffer(2)->data = (SDataWord_T *) currentScript()->bytecode->bytecode_p; @@ -275,7 +246,6 @@ int Script::SThreadRun(SCRIPT_THREAD *thread, int instr_limit) { in_char = scriptS.readByte(); debug(2, "Executing thread offset: %lu (%x) stack: %d", thread->i_offset, in_char, thread->stackSize()); - switch (in_char) { case 0x01: // nextblock // Some sort of "jump to the start of the next memory @@ -385,6 +355,7 @@ int Script::SThreadRun(SCRIPT_THREAD *thread, int instr_limit) { if (func_num >= SFUNC_NUM) { _vm->_console->DebugPrintf(S_ERROR_PREFIX "Invalid script function number: (%X)\n", func_num); thread->flags |= kTFlagAborted; + debug(9, "Invalid script function number: (%X)\n", func_num); break; } @@ -392,6 +363,7 @@ int Script::SThreadRun(SCRIPT_THREAD *thread, int instr_limit) { sfuncRetVal = (this->*sfunc)(thread, n_args); if (sfuncRetVal != SUCCESS) { _vm->_console->DebugPrintf(S_WARN_PREFIX "%X: Script function %d failed.\n", thread->i_offset, func_num); + debug(9, "%X: Script function %d failed.\n", thread->i_offset, func_num); } if (func_num == 16) { // SF_gotoScene @@ -421,6 +393,7 @@ int Script::SThreadRun(SCRIPT_THREAD *thread, int instr_limit) { if (thread->stackSize() == 0) { _vm->_console->DebugPrintf("Script execution complete.\n"); thread->flags |= kTFlagFinished; + debug(9, "Script execution complete.\n"); } else { thread->i_offset = thread->pop(); /* int n_args = */ thread->pop(); @@ -520,6 +493,7 @@ int Script::SThreadRun(SCRIPT_THREAD *thread, int instr_limit) { } if (!branch_found) { _vm->_console->DebugPrintf(S_ERROR_PREFIX "%X: Random jump target out of bounds.\n", thread->i_offset); + debug(9, "%X: Random jump target out of bounds.\n", thread->i_offset); } } break; @@ -758,6 +732,7 @@ int Script::SThreadRun(SCRIPT_THREAD *thread, int instr_limit) { a_index = _vm->_actor->getActorIndex(param1); if (a_index < 0) { _vm->_console->DebugPrintf(S_WARN_PREFIX "%X: DLGP Actor id not found.\n", thread->i_offset); + debug(9, "%X: DLGP Actor id not found.\n", thread->i_offset); } for (i = 0; i < n_voices; i++) { @@ -806,6 +781,7 @@ int Script::SThreadRun(SCRIPT_THREAD *thread, int instr_limit) { _vm->_console->DebugPrintf(S_ERROR_PREFIX "%X: Invalid opcode encountered: (%X).\n", thread->i_offset, in_char); thread->flags |= kTFlagAborted; + debug(9, "%X: Invalid opcode encountered: (%X).\n", thread->i_offset, in_char); break; } @@ -813,11 +789,18 @@ int Script::SThreadRun(SCRIPT_THREAD *thread, int instr_limit) { if (saved_offset == thread->i_offset) { thread->i_offset = scriptS.pos(); } else { - scriptS.seek(thread->i_offset); + if (thread->i_offset >= scriptS.size()) { + _vm->_console->DebugPrintf("Out of range script execution at %x size %x\n", thread->i_offset, scriptS.size()); + thread->flags |= kTFlagFinished; + debug(9, "Out of range script execution at %x size %x\n", thread->i_offset, scriptS.size()); + } + else + scriptS.seek(thread->i_offset); } if (unhandled) { _vm->_console->DebugPrintf(S_ERROR_PREFIX "%X: Unhandled opcode.\n", thread->i_offset); thread->flags |= kTFlagAborted; + debug(9, "%X: Unhandled opcode.\n", thread->i_offset); } if ((thread->flags == kTFlagNone) && debug_print) { SDebugPrintInstr(thread); diff --git a/saga/stream.h b/saga/stream.h new file mode 100644 index 0000000000..2ac45c79c5 --- /dev/null +++ b/saga/stream.h @@ -0,0 +1,56 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 The ScummVM project + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#ifndef SAGA_STREAM_H__ +#define SAGA_STREAM_H__ + +#include "common/stream.h" + +namespace Saga { + +using Common::MemoryReadStream; + +class MemoryReadStreamEndian : public Common::MemoryReadStream { +private: +public: + bool _bigEndian; + MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian = false) : MemoryReadStream(buf, len), _bigEndian(bigEndian) {} + + uint16 readUint16() { + return (_bigEndian) ? readUint16BE(): readUint16LE(); + } + + uint32 readUint32() { + return (_bigEndian) ? readUint32BE(): readUint32LE(); + } + + inline int16 readSint16() { + return (int16)readUint16(); + } + + + inline int32 readSint32() { + return (int32)readUint32(); + } +}; + +} // End of namespace Saga +#endif diff --git a/saga/text.cpp b/saga/text.cpp index be14528995..f7237e4006 100644 --- a/saga/text.cpp +++ b/saga/text.cpp @@ -24,7 +24,6 @@ // Text / dialogue display management module #include "saga/saga.h" -#include "saga/yslib.h" #include "saga/gfx.h" #include "saga/font.h" @@ -149,25 +148,18 @@ int SagaEngine::textDraw(int font_id, SURFACE *ds, const char *string, int text_ TEXTLIST *SagaEngine::textCreateList() { TEXTLIST *new_textlist; - new_textlist = (TEXTLIST *)malloc(sizeof *new_textlist); + new_textlist = new TEXTLIST; if (new_textlist == NULL) { return NULL; } - new_textlist->list = ys_dll_create(); - - if (new_textlist->list == NULL) { - free(new_textlist); - return NULL; - } - return new_textlist; } void SagaEngine::textClearList(TEXTLIST *tlist) { if (tlist != NULL) { - ys_dll_delete_all(tlist->list); + tlist->clear(); } return; @@ -175,21 +167,18 @@ void SagaEngine::textClearList(TEXTLIST *tlist) { void SagaEngine::textDestroyList(TEXTLIST *tlist) { if (tlist != NULL) { - ys_dll_destroy(tlist->list); - } - free(tlist); - + delete tlist; + } return; } int SagaEngine::textDrawList(TEXTLIST *textlist, SURFACE *ds) { TEXTLIST_ENTRY *entry_p; - YS_DL_NODE *walk_p; assert((textlist != NULL) && (ds != NULL)); - for (walk_p = ys_dll_head(textlist->list); walk_p != NULL; walk_p = ys_dll_next(walk_p)) { - entry_p = (TEXTLIST_ENTRY *)ys_dll_get_data(walk_p); + for (TEXTLIST::iterator texti = textlist->begin(); texti != textlist->end(); ++texti) { + entry_p = (TEXTLIST_ENTRY *)texti.operator->(); if (entry_p->display != 0) { textDraw(entry_p->font_id, ds, entry_p->string, entry_p->text_x, entry_p->text_y, entry_p->color, entry_p->effect_color, entry_p->flags); @@ -201,16 +190,13 @@ int SagaEngine::textDrawList(TEXTLIST *textlist, SURFACE *ds) { int SagaEngine::textProcessList(TEXTLIST *textlist, long ms) { TEXTLIST_ENTRY *entry_p; - YS_DL_NODE *walk_p; - YS_DL_NODE *temp_p; - for (walk_p = ys_dll_head(textlist->list); walk_p != NULL; walk_p = temp_p) { - temp_p = ys_dll_next(walk_p); - entry_p = (TEXTLIST_ENTRY *)ys_dll_get_data(walk_p); + for (TEXTLIST::iterator texti = textlist->begin(); texti != textlist->end(); ++texti) { + entry_p = (TEXTLIST_ENTRY *)texti.operator->(); if (entry_p->flags & TEXT_TIMEOUT) { entry_p->time -= ms; if (entry_p->time <= 0) { - ys_dll_delete(walk_p); + texti=textlist->eraseAndPrev(texti); } } } @@ -220,13 +206,10 @@ int SagaEngine::textProcessList(TEXTLIST *textlist, long ms) { } TEXTLIST_ENTRY *SagaEngine::textAddEntry(TEXTLIST *textlist, TEXTLIST_ENTRY *entry) { - YS_DL_NODE *new_node = NULL; - if (entry != NULL) { - new_node = ys_dll_add_tail(textlist->list, entry, sizeof *entry); + return textlist->pushBack(*entry).operator->(); } - - return (new_node != NULL) ? (TEXTLIST_ENTRY *)new_node->data : NULL; + return NULL; } int SagaEngine::textSetDisplay(TEXTLIST_ENTRY *entry, int val) { @@ -239,18 +222,12 @@ int SagaEngine::textSetDisplay(TEXTLIST_ENTRY *entry, int val) { } int SagaEngine::textDeleteEntry(TEXTLIST *textlist, TEXTLIST_ENTRY *entry) { - YS_DL_NODE *walk_p; if (entry == NULL) { return FAILURE; } - - for (walk_p = ys_dll_head(textlist->list); walk_p != NULL; walk_p = ys_dll_next(walk_p)) { - if (entry == ys_dll_get_data(walk_p)) { - ys_dll_delete(walk_p); - break; - } - } + + textlist->remove(entry); return SUCCESS; } diff --git a/saga/text.h b/saga/text.h index f56113f278..460d9f74b8 100644 --- a/saga/text.h +++ b/saga/text.h @@ -26,7 +26,7 @@ #ifndef SAGA_TEXT_H__ #define SAGA_TEXT_H__ -#include "saga/yslib.h" +#include "saga/list.h" namespace Saga { @@ -34,17 +34,12 @@ namespace Saga { #define TEXT_MARGIN 10 #define TEXT_LINESPACING 2 -struct TEXTLIST { - YS_DL_LIST *list; -}; enum TEXT_FLAGS { TEXT_TIMEOUT = 0x01 }; struct TEXTLIST_ENTRY { - TEXTLIST_ENTRY *next; - TEXTLIST_ENTRY *prev; int display; int id; int text_x; @@ -58,6 +53,9 @@ struct TEXTLIST_ENTRY { TEXTLIST_ENTRY() { memset(this, 0, sizeof(*this)); } }; +typedef SortedList TEXTLIST; + +#define TEXTLISTITERATOR TEXTLIST::iterator } // End of namespace Saga #endif diff --git a/saga/ys_dl_list.cpp b/saga/ys_dl_list.cpp deleted file mode 100644 index db7adfe4ce..0000000000 --- a/saga/ys_dl_list.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2004 The ScummVM project - * - * The ReInherit Engine is (C)2000-2003 by Daniel Balsom. - * - * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ -#include "saga/saga.h" -#include "saga/yslib.h" - -namespace Saga { - -YS_DL_LIST *ys_dll_create() { - YS_DL_LIST *new_list; - - new_list = (YS_DL_LIST *)malloc(sizeof *new_list); - - if (new_list != NULL) { - new_list->next = new_list; - new_list->prev = new_list; - - // Sentinel is marked by self-referential node data. - // No other link is permitted to do this - new_list->data = new_list; - } - - return new_list; -} - -void ys_dll_destroy(YS_DL_LIST *list) { - YS_DL_NODE *walk_p; - YS_DL_NODE *temp_p; - - for (walk_p = list->next; walk_p != list; walk_p = temp_p) { - temp_p = walk_p->next; - free(walk_p->data); - free(walk_p); - } - - free(list); - - return; -} - -void *ys_dll_get_data(YS_DL_NODE *node) { - return node->data; -} - -YS_DL_NODE *ys_dll_head(YS_DL_LIST *list) { - return (list->next != list) ? list->next : NULL; -} - -YS_DL_NODE *ys_dll_tail(YS_DL_LIST *list) { - return (list->prev != list) ? list->prev : NULL; -} - -YS_DL_NODE *ys_dll_next(YS_DL_NODE *node) { - return (node->next != (YS_DL_LIST *) node->next->data) ? node->next : NULL; -} - -YS_DL_NODE *ys_dll_prev(YS_DL_NODE *node) { - return (node->prev != (YS_DL_LIST *) node->prev->data) ? node->prev : NULL; -} - -YS_DL_NODE *ys_dll_add_head(YS_DL_LIST *list, void *data, size_t size) { - YS_DL_NODE *new_node; - void *new_data; - - new_node = (YS_DL_NODE *)malloc(sizeof *new_node); - - if (new_node) { - new_data = malloc(size); - - if (new_data) { - memcpy(new_data, data, size); - new_node->data = new_data; - new_node->prev = list; - new_node->next = list->next; - new_node->next->prev = new_node; - list->next = new_node; - } - } - return new_node; -} - -YS_DL_NODE *ys_dll_add_tail(YS_DL_LIST *list, void *data, size_t size) { - YS_DL_NODE *new_node; - void *new_data; - - new_node = (YS_DL_NODE *)malloc(sizeof *new_node); - - if (new_node != NULL) { - new_data = malloc(size); - - if (new_data != NULL) { - memcpy(new_data, data, size); - new_node->data = new_data; - new_node->next = list; - new_node->prev = list->prev; - new_node->prev->next = new_node; - list->prev = new_node; - } - } - return new_node; -} - -YS_DL_NODE *ys_dll_insert(YS_DL_NODE *list, void *data, size_t size, YS_COMPARE_FUNC *compare) { - YS_DL_NODE *walk_p; - YS_DL_NODE *new_node; - int result; - - for (walk_p = list->next; walk_p != list; walk_p = walk_p->next) { - result = compare(data, walk_p->data); - if (result < 0) { - new_node = ys_dll_preinsert(walk_p, data, size); - return new_node; - } - } - - new_node = ys_dll_add_tail(list, data, size); - return new_node; -} - -int ys_dll_delete(YS_DL_NODE *node) { - if (node == NULL) { - return YS_E_FAILURE; - } - - node->next->prev = node->prev; - node->prev->next = node->next; - - free(node->data); - free(node); - - return YS_E_SUCCESS; -} - -void ys_dll_delete_all(YS_DL_LIST *list) { - YS_DL_NODE *walk_p; - YS_DL_NODE *temp_p; - - for (walk_p = list->next; walk_p != list; walk_p = temp_p) { - temp_p = walk_p->next; - free(walk_p->data); - free(walk_p); - } - - list->next = list; - list->prev = list; -} - -YS_DL_NODE *ys_dll_replace(YS_DL_NODE *node, void *data, size_t size) { - void *new_data; - - if ((node == NULL) || (data == NULL) || (!size)) { - return NULL; - } - - new_data = malloc(size); - - if (new_data == NULL) { - return NULL; - } - - free(node->data); - node->data = new_data; - memcpy(new_data, data, size); - - return node; -} - -int ys_dll_reorder_up(YS_DL_NODE *list, YS_DL_NODE *olink, YS_COMPARE_FUNC *compare) { - YS_DL_NODE *walk_p; - int result; - int reorder = 0; - - for (walk_p = olink->prev; walk_p != list; walk_p = walk_p->prev) { - result = compare(walk_p->data, olink->data); - if (result <= 0) { - reorder = 1; - break; - } - } - - if (reorder) { - // Unlink original link - olink->next->prev = olink->prev; - olink->prev->next = olink->next; - // Reinsert after walk link - olink->prev = walk_p; - olink->next = walk_p->next; - olink->next->prev = olink; - walk_p->next = olink; - } - return YS_E_SUCCESS; -} - -int ys_dll_reorder_down(YS_DL_NODE *list, YS_DL_NODE *olink, YS_COMPARE_FUNC *compare) { - YS_DL_NODE *walk_p; - int result; - int reorder = 0; - - for (walk_p = olink->next; walk_p != list; walk_p = walk_p->next) { - result = compare(walk_p->data, olink->data); - if (result >= 0) { - reorder = 1; - break; - } - } - - if (reorder) { - // Unlink original link - olink->next->prev = olink->prev; - olink->prev->next = olink->next; - //Reinsert before walk link - olink->next = walk_p; - olink->prev = walk_p->prev; - olink->prev->next = olink; - walk_p->prev = olink; - } - return YS_E_SUCCESS; -} - -} // End of namespace Saga diff --git a/saga/yslib.h b/saga/yslib.h deleted file mode 100644 index d6f9000c26..0000000000 --- a/saga/yslib.h +++ /dev/null @@ -1,90 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2004 The ScummVM project - * - * The ReInherit Engine is (C)2000-2003 by Daniel Balsom. - * - * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ -#ifndef YSLIB_MAIN_H__ -#define YSLIB_MAIN_H__ - -namespace Saga { - -enum YS_ERROR_STATES { - YS_E_SUCCESS = 0, - YS_E_FAILURE, - YS_E_MEM -}; - -enum YS_CONFIRM_STATES { - YS_CONFIRM_NO = 0, - YS_CONFIRM_YES, - YS_CONFIRM_CANCEL -}; - -// General purpose quantity-comparison function -typedef int (YS_COMPARE_FUNC) (const void *, const void *); - -// General-purpose utility macros - -//#define YS_ASSUME_2S_COMP - -// Shared declarations for list modules -enum YS_WALK_DIRECTIONS { - YS_WALK_BACKWARD = 0, - YS_WALK_FORWARD -}; - -typedef struct ys_dl_node_tag YS_DL_NODE; -typedef struct ys_dl_node_tag YS_DL_LIST; - -struct ys_dl_node_tag { - void *data; - struct ys_dl_node_tag *next; - struct ys_dl_node_tag *prev; -}; - -YS_DL_LIST *ys_dll_create(); -void ys_dll_destroy(YS_DL_LIST *); - -void *ys_dll_get_data(YS_DL_NODE *); - -YS_DL_NODE *ys_dll_head(YS_DL_LIST *); -YS_DL_NODE *ys_dll_tail(YS_DL_LIST *); -YS_DL_NODE *ys_dll_next(YS_DL_NODE *); -YS_DL_NODE *ys_dll_prev(YS_DL_NODE *); - -YS_DL_NODE *ys_dll_add_head(YS_DL_LIST *, void *, size_t); -YS_DL_NODE *ys_dll_add_tail(YS_DL_LIST *, void *, size_t); - -#define ys_dll_preinsert ys_dll_add_tail -#define ys_dll_postinsert ys_dll_add_head - -YS_DL_NODE *ys_dll_insert(YS_DL_LIST *, void *, size_t, YS_COMPARE_FUNC *); -int ys_dll_delete(YS_DL_NODE *); -void ys_dll_delete_all(YS_DL_LIST *); - -YS_DL_NODE *ys_dll_replace(YS_DL_NODE *, void *, size_t); - -int ys_dll_reorder_up(YS_DL_LIST *, YS_DL_NODE *, YS_COMPARE_FUNC *); -int ys_dll_reorder_down(YS_DL_LIST *, YS_DL_NODE *, YS_COMPARE_FUNC *); - - -} // End of namespace Saga - -#endif -- cgit v1.2.3