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
This commit is contained in:
parent
58eabb6a5f
commit
502b279d24
36 changed files with 928 additions and 954 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
318
saga/actor.cpp
318
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);
|
||||
actorIterator = _list.pushBack(*actor, actorCompare);
|
||||
|
||||
if (new_node == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
actor = actorIterator.operator->();
|
||||
|
||||
actor = (ACTOR *)ys_dll_get_data(new_node);
|
||||
actor->node = new_node;
|
||||
|
||||
_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);
|
||||
|
|
123
saga/actor.h
123
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<WALKNODE> 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<ACTORDIALOGUE> 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<ACTORINTENT> 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<ACTOR> 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
|
||||
|
|
|
@ -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();
|
||||
case SAGA_FRAME_REPOSITION: // Reposition command
|
||||
readS.readSint16BE();
|
||||
continue;
|
||||
break;
|
||||
case SAGA_FRAME_ROW_END: // End of row marker
|
||||
readS.readSint16BE();
|
||||
if (IS_MAC_VERSION)
|
||||
readS.readSint16BE();
|
||||
else
|
||||
readS.readByte();
|
||||
continue;
|
||||
break;
|
||||
case SAGA_FRAME_LONG_COMPRESSED_RUN: // Long compressed run marker
|
||||
readS.readSint16BE();
|
||||
readS.readByte();
|
||||
continue;
|
||||
break;
|
||||
case 0x2F: // End of row marker
|
||||
readS.readByte();
|
||||
readS.readByte();
|
||||
readS.readByte();
|
||||
continue;
|
||||
break;
|
||||
case 0x20: // Long compressed run marker
|
||||
readS.readByte();
|
||||
readS.readByte();
|
||||
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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
|
||||
|
|
|
@ -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<EVENT> 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
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
154
saga/list.h
Normal file
154
saga/list.h
Normal file
|
@ -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 T>
|
||||
class SortedList : public Common::List<T> {
|
||||
public:
|
||||
typedef int ( CompareFunction ) (const T& , const T&);
|
||||
|
||||
typedef typename Common::List<T>::iterator iterator;
|
||||
typedef typename Common::List<T>::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<T>::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<T>::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<T>::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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ class Console;
|
|||
class Events;
|
||||
class PalAnim;
|
||||
|
||||
using Common::MemoryReadStream;
|
||||
|
||||
#define PBOUNDS(n,max) (((n)>=(0))&&((n)<(max)))
|
||||
#define MAXPATH 512
|
||||
|
|
126
saga/scene.cpp
126
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);
|
||||
|
||||
if (queueIterator == _sceneQueue.end()) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
ys_dll_delete(node);
|
||||
|
||||
// Load the head node in scene queue
|
||||
node = ys_dll_head(_sceneQueue);
|
||||
if (node == NULL) {
|
||||
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;
|
||||
}
|
||||
MemoryReadStreamEndian readS(scene_desc_data, scene_desc_len, IS_BIG_ENDIAN);
|
||||
|
||||
MemoryReadStream readS(scene_desc_data, scene_desc_len);
|
||||
|
||||
_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;
|
||||
|
||||
|
|
11
saga/scene.h
11
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<SCENE_ANIMINFO> SceneAnimInfoList;
|
||||
|
||||
enum SCENE_FADE_TYPES {
|
||||
SCENE_NOFADE = 0,
|
||||
SCENE_FADE = 1,
|
||||
|
@ -154,6 +157,8 @@ struct SCENE_QUEUE {
|
|||
int fadeType;
|
||||
};
|
||||
|
||||
typedef Common::List<SCENE_QUEUE> 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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<SCRIPT_THREAD> 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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
56
saga/stream.h
Normal file
56
saga/stream.h
Normal file
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
10
saga/text.h
10
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_ENTRY> TEXTLIST;
|
||||
|
||||
#define TEXTLISTITERATOR TEXTLIST::iterator
|
||||
|
||||
} // End of namespace Saga
|
||||
#endif
|
||||
|
|
|
@ -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
|
90
saga/yslib.h
90
saga/yslib.h
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue