aboutsummaryrefslogtreecommitdiff
path: root/saga
diff options
context:
space:
mode:
authorAndrew Kurushin2005-06-11 17:24:06 +0000
committerAndrew Kurushin2005-06-11 17:24:06 +0000
commitd9a38f6f55262a945a9ae2a56f4eb0bed1b54551 (patch)
tree0b67996511159b6e09565328e3eb0fa721978a50 /saga
parentcf80e36831c4c09961e5153d9edcdf8083d2ae4e (diff)
downloadscummvm-rg350-d9a38f6f55262a945a9ae2a56f4eb0bed1b54551.tar.gz
scummvm-rg350-d9a38f6f55262a945a9ae2a56f4eb0bed1b54551.tar.bz2
scummvm-rg350-d9a38f6f55262a945a9ae2a56f4eb0bed1b54551.zip
rewritten animation loading
removed animation warnings during game process svn-id: r18377
Diffstat (limited to 'saga')
-rw-r--r--saga/animation.cpp502
-rw-r--r--saga/animation.h133
-rw-r--r--saga/scene.cpp58
3 files changed, 297 insertions, 396 deletions
diff --git a/saga/animation.cpp b/saga/animation.cpp
index 6bc97b5be7..8aa1dcecd0 100644
--- a/saga/animation.cpp
+++ b/saga/animation.cpp
@@ -34,232 +34,189 @@
namespace Saga {
Anim::Anim(SagaEngine *vm) : _vm(vm) {
- int i;
-
- _anim_limit = MAX_ANIMATIONS;
- _anim_count = 0;
+ uint16 i;
for (i = 0; i < MAX_ANIMATIONS; i++)
- _anim_tbl[i] = NULL;
-
- _initialized = true;
+ _animations[i] = NULL;
}
Anim::~Anim(void) {
- uint16 i;
-
- for (i = 0; i < MAX_ANIMATIONS; i++)
- free(_anim_tbl[i]);
-
- _initialized = false;
+ reset();
}
-int Anim::load(const byte *anim_resdata, size_t anim_resdata_len, uint16 *anim_id_p) {
- ANIMATION *new_anim;
- ANIMATION_HEADER ah;
-
- uint16 anim_id = 0;
+uint16 Anim::load(const byte *animResourceData, size_t animResourceLength) {
+ AnimationData *anim;
+ uint16 animId = 0;
uint16 i;
- if (!_initialized) {
- warning("Anim::load not initialised");
- return FAILURE;
- }
-
// Find an unused animation slot
for (i = 0; i < MAX_ANIMATIONS; i++) {
- if (_anim_tbl[i] == NULL) {
- anim_id = i;
+ if (_animations[i] == NULL) {
+ animId = i;
break;
}
}
- if (i == MAX_ANIMATIONS) {
- warning("Anim::load could not find unused animation slot");
- return FAILURE;
+ if (animId == MAX_ANIMATIONS) {
+ error("Anim::load could not find unused animation slot");
}
- new_anim = (ANIMATION *)malloc(sizeof(*new_anim));
- if (new_anim == NULL) {
- warning("Anim::load Allocation failure");
- return MEM;
- }
+ anim = _animations[animId] = new AnimationData(animResourceData, animResourceLength);
- new_anim->resdata = anim_resdata;
- new_anim->resdata_len = anim_resdata_len;
+ MemoryReadStreamEndian headerReadS(anim->resourceData, anim->resourceLength, IS_BIG_ENDIAN);
+ anim->magic = headerReadS.readUint16LE(); // cause ALWAYS LE
+ anim->screenWidth = headerReadS.readUint16();
+ anim->screenHeight = headerReadS.readUint16();
- MemoryReadStreamEndian headerReadS(anim_resdata, anim_resdata_len, IS_BIG_ENDIAN);
+ anim->unknown06 = headerReadS.readByte();
+ anim->unknown07 = headerReadS.readByte();
+ anim->maxFrame = headerReadS.readByte() - 1;
+ anim->loopFrame = headerReadS.readByte() - 1;
+ anim->start = headerReadS.readUint16BE();
+
+ if (anim->start != 65535 && anim->start != 0)
+ warning("Anim::load: found different start: %d. Fix Anim::play()", anim->start);
+ anim->start += headerReadS.pos();
- readAnimHeader(headerReadS, ah);
- new_anim->maxframe = ah.maxframe;
- new_anim->loopframe = ah.loopframe;
if (_vm->getGameType() == GType_ITE) {
// Cache frame offsets
- new_anim->frame_offsets = (size_t *)malloc((new_anim->maxframe + 1) * sizeof(*new_anim->frame_offsets));
- if (new_anim->frame_offsets == NULL) {
- warning("Anim::load Allocation failure");
- return MEM;
+ anim->frameOffsets = (size_t *)malloc((anim->maxFrame + 1) * sizeof(*anim->frameOffsets));
+ if (anim->frameOffsets == NULL) {
+ memoryError("Anim::load");
}
- for (i = 0; i <= new_anim->maxframe; i++) {
- getFrameOffset(anim_resdata, anim_resdata_len, i, &new_anim->frame_offsets[i]);
- }
+ fillFrameOffsets(anim);
} else {
- 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;
+ anim->cur_frame_p = anim->resourceData + SAGA_FRAME_HEADER_LEN; // ? len - may vary
+ anim->cur_frame_len = anim->resourceLength - SAGA_FRAME_HEADER_LEN;
}
// Set animation data
- new_anim->current_frame = 0;
- new_anim->completed = 0;
- new_anim->cycles = new_anim->maxframe;
-
- new_anim->frame_time = DEFAULT_FRAME_TIME;
- new_anim->flags = 0;
- new_anim->link_id = -1;
- new_anim->state = ANIM_PAUSE;
+ anim->currentFrame = 0;
+ anim->completed = 0;
+ anim->cycles = anim->maxFrame;
- _anim_tbl[anim_id] = new_anim;
+ anim->frameTime = DEFAULT_FRAME_TIME;
+ anim->flags = 0;
+ anim->linkId = -1;
+ anim->state = ANIM_PAUSE;
- *anim_id_p = anim_id;
-
- _anim_count++;
-
- return SUCCESS;
+ return animId;
}
-int Anim::link(int16 anim_id1, int16 anim_id2) {
- ANIMATION *anim1;
- ANIMATION *anim2;
-
- if ((anim_id1 >= _anim_count) || (anim_id2 >= _anim_count)) {
- return FAILURE;
- }
-
- anim1 = _anim_tbl[anim_id1];
+void Anim::link(int16 animId1, int16 animId2) {
+ AnimationData *anim1;
+ AnimationData *anim2;
- anim1->link_id = anim_id2;
+ anim1 = getAnimation(animId1);
- if (anim_id2 == -1)
- return SUCCESS;
+ anim1->linkId = animId2;
- anim2 = _anim_tbl[anim_id2];
-
- if ((anim1 == NULL) || (anim2 == NULL)) {
- return FAILURE;
+ if (animId2 == -1) {
+ return;
}
- anim2->frame_time = anim1->frame_time;
-
- return SUCCESS;
+ anim2 = getAnimation(animId2);
+ anim2->frameTime = anim1->frameTime;
}
-void Anim::setCycles(uint animId, int cycles) {
- if (animId >= _anim_count) {
- warning("Anim::setCycles(): wrong animation number (%d)", animId);
- return;
- }
+void Anim::setCycles(uint16 animId, int cycles) {
+ AnimationData *anim;
+
+ anim = getAnimation(animId);
- _anim_tbl[animId]->cycles = cycles;
+ anim->cycles = cycles;
}
-int Anim::play(uint16 anim_id, int vector_time, bool playing) {
+void Anim::play(uint16 animId, int vectorTime, bool playing) {
EVENT event;
- ANIMATION *anim;
- ANIMATION *link_anim;
- uint16 link_anim_id;
-
BUFFER_INFO buf_info;
- byte *display_buf;
+ byte *displayBuffer;
const byte *nextf_p;
size_t nextf_len;
uint16 frame;
- int frame_time;
+ int frameTime;
int result;
- if (anim_id >= _anim_count) {
- return FAILURE;
- }
+ AnimationData *anim;
+ AnimationData *linkAnim;
+
+ anim = getAnimation(animId);
+
_vm->_render->getBufferInfo(&buf_info);
- display_buf = buf_info.bg_buf;
+ displayBuffer = buf_info.bg_buf;
- anim = _anim_tbl[anim_id];
- if (anim == NULL) {
- return FAILURE;
- }
- if (playing)
+ if (playing) {
anim->state = ANIM_PLAYING;
+ }
- if (anim->state == ANIM_PAUSE)
- return SUCCESS;
+ if (anim->state == ANIM_PAUSE) {
+ return;
+ }
if (anim->completed < anim->cycles) {
- frame = anim->current_frame;
+ frame = anim->currentFrame;
if (_vm->getGameType() == GType_ITE) {
// FIXME: if start > 0, then this works incorrectly
- result = ITE_DecodeFrame(anim->resdata, anim->resdata_len, anim->frame_offsets[frame], display_buf,
- _vm->getDisplayWidth() * _vm->getDisplayHeight());
- if (result != SUCCESS) {
- warning("Anim::play: Error decoding frame %u", anim->current_frame);
- anim->state = ANIM_PAUSE;
- return FAILURE;
- }
+ ITE_DecodeFrame(anim, anim->frameOffsets[frame], displayBuffer,
+ _vm->getDisplayWidth() * _vm->getDisplayHeight());
} else {
if (anim->cur_frame_p == NULL) {
warning("Anim::play: Frames exhausted");
- return FAILURE;
+ return;
}
- result = IHNM_DecodeFrame(display_buf, _vm->getDisplayWidth() * _vm->getDisplayHeight(),
+ result = IHNM_DecodeFrame(displayBuffer, _vm->getDisplayWidth() * _vm->getDisplayHeight(),
anim->cur_frame_p, anim->cur_frame_len, &nextf_p, &nextf_len);
if (result != SUCCESS) {
- warning("Anim::play: Error decoding frame %u", anim->current_frame);
+ warning("Anim::play: Error decoding frame %u", anim->currentFrame);
anim->state = ANIM_PAUSE;
- return FAILURE;
+ return;
}
anim->cur_frame_p = nextf_p;
anim->cur_frame_len = nextf_len;
}
- anim->current_frame++;
+
+ anim->currentFrame++;
anim->completed++;
- if (anim->current_frame > anim->maxframe) {
- anim->current_frame = anim->loopframe;
+ if (anim->currentFrame > anim->maxFrame) {
+ anim->currentFrame = anim->loopFrame;
- // FIXME: HACK. probably needs more testing for IHNM
- anim->cur_frame_p = anim->resdata + SAGA_FRAME_HEADER_LEN;
- anim->cur_frame_len = anim->resdata_len - SAGA_FRAME_HEADER_LEN;
-
- if (anim->flags & ANIM_STOPPING || anim->current_frame == -1)
+ if (_vm->getGameType() == GType_IHNM) {
+ // FIXME: HACK. probably needs more testing for IHNM
+ anim->cur_frame_p = anim->resourceData + SAGA_FRAME_HEADER_LEN;
+ anim->cur_frame_len = anim->resourceLength - SAGA_FRAME_HEADER_LEN;
+ }
+
+ if (anim->flags & ANIM_STOPPING || anim->currentFrame == (uint16)-1) {
anim->state = ANIM_PAUSE;
+ }
}
} else {
// Animation done playing
- if (anim->link_id != -1) {
+ if (anim->linkId != -1) {
// If this animation has a link, follow it
- anim->current_frame = 0;
+ anim->currentFrame = 0;
anim->state = ANIM_PAUSE;
- link_anim_id = anim->link_id;
- link_anim = _anim_tbl[link_anim_id];
+/* linkAnim = getAnimation(anim->linkId);
- if (link_anim != NULL) {
- link_anim->current_frame = 0;
- link_anim->state = ANIM_PLAYING;
- }
+ linkAnim->currentFrame = 0;
+ linkAnim->state = ANIM_PLAYING;
- anim_id = link_anim_id;
+ animId = anim->linkId;*/
} else {
// No link, stop playing
- anim->current_frame = anim->maxframe;
+ anim->currentFrame = anim->maxFrame;
anim->state = ANIM_PAUSE;
if (anim->flags & ANIM_ENDSCENE) {
@@ -267,183 +224,115 @@ int Anim::play(uint16 anim_id, int vector_time, bool playing) {
event.type = ONESHOT_EVENT;
event.code = SCENE_EVENT;
event.op = EVENT_END;
- event.time = anim->frame_time + vector_time;
+ event.time = anim->frameTime + vectorTime;
_vm->_events->queue(&event);
}
- return SUCCESS;
+ return;
}
}
- if (anim->state == ANIM_PAUSE && anim->link_id != -1) {
+ if (anim->state == ANIM_PAUSE && anim->linkId != -1) {
// If this animation has a link, follow it
- link_anim_id = anim->link_id;
- link_anim = _anim_tbl[link_anim_id];
+ linkAnim = getAnimation(anim->linkId);
- if (link_anim != NULL) {
- debug(5, "Animation ended going to %d", link_anim_id);
- link_anim->current_frame = 0;
- link_anim->state = ANIM_PLAYING;
- }
- anim_id = link_anim_id;
- frame_time = 0;
+ debug(5, "Animation ended going to %d", anim->linkId);
+ linkAnim->currentFrame = 0;
+ linkAnim->state = ANIM_PLAYING;
+ animId = anim->linkId;
+ frameTime = 0;
} else {
- frame_time = anim->frame_time + vector_time;
+ frameTime = anim->frameTime + vectorTime;
}
event.type = ONESHOT_EVENT;
event.code = ANIM_EVENT;
event.op = EVENT_FRAME;
- event.param = anim_id;
- event.time = frame_time;
+ event.param = animId;
+ event.time = frameTime;
_vm->_events->queue(&event);
- return SUCCESS;
}
void Anim::stop(uint16 animId) {
- if (animId >= _anim_count) {
- warning("Anim::stop(): wrong animation number (%d)", animId);
- return;
- }
-
- _anim_tbl[animId]->state = ANIM_PAUSE;
+ AnimationData *anim;
+
+ anim = getAnimation(animId);
+
+ anim->state = ANIM_PAUSE;
}
void Anim::finish(uint16 animId) {
- if (animId >= _anim_count) {
- warning("Anim::finish(): wrong animation number (%d)", animId);
- return;
- }
-
- _anim_tbl[animId]->state = ANIM_STOPPING;
+ AnimationData *anim;
+
+ anim = getAnimation(animId);
+
+ anim->state = ANIM_STOPPING;
}
void Anim::resume(uint16 animId, int cycles) {
- if (animId >= _anim_count) {
- warning("Anim::resume(): wrong animation number (%d)", animId);
- return;
- }
+ AnimationData *anim;
+
+ anim = getAnimation(animId);
- _anim_tbl[animId]->cycles += cycles;
+ anim->cycles += cycles;
play(animId, 0, true);
}
-int Anim::reset() {
+void Anim::reset() {
uint16 i;
for (i = 0; i < MAX_ANIMATIONS; i++) {
- freeId(i);
+ if (_animations[i] != NULL) {
+ delete _animations[i];
+ _animations[i] = NULL;
+ }
}
-
- return SUCCESS;
}
-int Anim::setFlag(uint16 anim_id, uint16 flag) {
- ANIMATION *anim;
+void Anim::setFlag(uint16 animId, uint16 flag) {
+ AnimationData *anim;
- if (anim_id > _anim_count) {
- return FAILURE;
- }
-
- anim = _anim_tbl[anim_id];
- if (anim == NULL) {
- return FAILURE;
- }
+ anim = getAnimation(animId);
anim->flags |= flag;
-
- return SUCCESS;
}
-int Anim::clearFlag(uint16 anim_id, uint16 flag) {
- ANIMATION *anim;
+void Anim::clearFlag(uint16 animId, uint16 flag) {
+ AnimationData *anim;
- if (anim_id > _anim_count) {
- return FAILURE;
- }
-
- anim = _anim_tbl[anim_id];
- if (anim == NULL) {
- return FAILURE;
- }
+ anim = getAnimation(animId);
anim->flags &= ~flag;
-
- return SUCCESS;
}
-int Anim::setFrameTime(uint16 anim_id, int time) {
- ANIMATION *anim;
-
- if (anim_id > _anim_count) {
- return FAILURE;
- }
-
- anim = _anim_tbl[anim_id];
- if (anim == NULL) {
- return FAILURE;
- }
+void Anim::setFrameTime(uint16 animId, int time) {
+ AnimationData *anim;
- anim->frame_time = time;
+ anim = getAnimation(animId);
- return SUCCESS;
+ anim->frameTime = time;
}
int16 Anim::getCurrentFrame(uint16 animId) {
- if (animId >= _anim_count) {
- warning("Anim::stop(): wrong animation number (%d)", animId);
- return 0;
- }
-
- return _anim_tbl[animId]->current_frame;
-}
+ AnimationData *anim;
-void Anim::freeId(uint16 animId) {
- ANIMATION *anim;
-
- anim = _anim_tbl[animId];
- if (anim == NULL) {
- return;
- }
-
- if (_vm->getGameType() == GType_ITE) {
- free(anim->frame_offsets);
- }
-
- free(anim);
- _anim_tbl[animId] = NULL;
- _anim_count--;
-}
-
-void Anim::readAnimHeader(MemoryReadStreamEndian &readS, ANIMATION_HEADER &ah) {
- 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();
- ah.maxframe = readS.readByte() - 1;
- ah.loopframe = readS.readByte() - 1;
- ah.start = readS.readUint16BE();
-
- if (ah.start != 65535 && ah.start != 0)
- warning("Anim::readAnimHeader(): found different start: %d. Fix Anim::play()", ah.start);
- ah.start += readS.pos();
+ anim = getAnimation(animId);
+
+ return anim->currentFrame;
}
-int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_offset, byte *buf, size_t buf_len) {
- ANIMATION_HEADER ah;
+void Anim::ITE_DecodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_t bufLength) {
FRAME_HEADER fh;
byte *write_p;
uint16 magic;
- uint16 x_start;
- uint16 y_start;
- uint32 screen_w;
- uint32 screen_h;
+ uint16 xStart;
+ uint16 yStart;
+ uint32 screenWidth;
+ uint32 screenHeight;
int mark_byte;
byte data_byte;
@@ -457,59 +346,52 @@ int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_
uint16 i;
- if (!_initialized) {
- return FAILURE;
- }
+ screenWidth = anim->screenWidth;
+ screenHeight = anim->screenHeight;
- MemoryReadStreamEndian headerReadS(resdata, resdata_len, IS_BIG_ENDIAN);
-
- readAnimHeader(headerReadS, ah);
-
- screen_w = ah.screen_w;
- screen_h = ah.screen_h;
-
- if ((screen_w * screen_h) > buf_len) {
+ if ((screenWidth * screenHeight) > bufLength) {
// Buffer argument is too small to hold decoded frame, abort.
- warning("ITE_DecodeFrame: Buffer size inadequate");
- return FAILURE;
+ error("ITE_DecodeFrame: Buffer size inadequate");
}
- MemoryReadStream readS(resdata + frame_offset, resdata_len - frame_offset);
+ MemoryReadStream readS(anim->resourceData + frameOffset, anim->resourceLength - frameOffset);
// Check for frame magic byte
magic = readS.readByte();
+ if (magic == SAGA_FRAME_END) {
+ return;
+ }
+
if (magic != SAGA_FRAME_START) {
- warning("ITE_DecodeFrame: Invalid frame offset %x", frame_offset);
- return FAILURE;
+ error("ITE_DecodeFrame: Invalid frame offset %x", frameOffset);
}
- fh.x_start = readS.readUint16BE();
+ fh.xStart = readS.readUint16BE();
if (_vm->getFeatures() & GF_BIG_ENDIAN_DATA)
- fh.y_start = readS.readUint16BE();
+ fh.yStart = readS.readUint16BE();
else
- fh.y_start = readS.readByte();
+ fh.yStart = readS.readByte();
readS.readByte(); /* Skip pad byte */
- fh.x_pos = readS.readUint16BE();
- fh.y_pos = readS.readUint16BE();
+ fh.xPos = readS.readUint16BE();
+ fh.yPos = readS.readUint16BE();
fh.width = readS.readUint16BE();
fh.height = readS.readUint16BE();
- x_start = fh.x_start;
- y_start = fh.y_start;
+ xStart = fh.xStart;
+ yStart = fh.yStart;
#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; \
+ if ((write_p < buf) || (write_p >= (buf + screenWidth * screenHeight))) { \
+ error("VALIDATE_WRITE_POINTER: write_p=%x buf=%x", write_p, buf); \
}
#else
#define VALIDATE_WRITE_POINTER
#endif
// Setup write pointer to the draw origin
- write_p = (buf + (y_start * screen_w) + x_start);
+ write_p = (buf + (yStart * screenWidth) + xStart);
VALIDATE_WRITE_POINTER;
// Begin RLE decompression to output buffer
@@ -546,7 +428,7 @@ int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_
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;
+ write_p = buf + ((yStart + new_row) * screenWidth) + xStart + x_vector;
VALIDATE_WRITE_POINTER;
continue;
break;
@@ -557,7 +439,7 @@ int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_
continue;
break;
case SAGA_FRAME_END: // End of frame marker
- return SUCCESS;
+ return;
break;
default:
break;
@@ -599,13 +481,11 @@ int Anim::ITE_DecodeFrame(const byte *resdata, size_t resdata_len, size_t frame_
break;
default:
// Unknown marker found - abort
- warning("ITE_DecodeFrame: Invalid RLE marker encountered");
- return FAILURE;
+ error("ITE_DecodeFrame: Invalid RLE marker encountered");
break;
}
} while (mark_byte != 63); // end of frame marker
- return SUCCESS;
}
int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_p,
@@ -829,10 +709,8 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *
return SUCCESS;
}
-int Anim::getFrameOffset(const byte *resdata, size_t resdata_len, uint16 find_frame, size_t *frame_offset_p) {
- ANIMATION_HEADER ah;
-
- uint16 current_frame;
+void Anim::fillFrameOffsets(AnimationData *anim) {
+ uint16 currentFrame;
byte mark_byte;
uint16 control;
@@ -841,27 +719,28 @@ int Anim::getFrameOffset(const byte *resdata, size_t resdata_len, uint16 find_fr
int i;
- MemoryReadStreamEndian readS(resdata, resdata_len, IS_BIG_ENDIAN);
-
- readAnimHeader(readS, ah);
+ MemoryReadStreamEndian readS(anim->resourceData, anim->resourceLength, IS_BIG_ENDIAN);
- if (find_frame > ah.maxframe) {
- return FAILURE;
- }
+ readS.seek(12);
+
readS._bigEndian = !IS_BIG_ENDIAN; // RLE has inversion BE<>LE
- for (current_frame = 0; current_frame < find_frame; current_frame++) {
+ for (currentFrame = 0; currentFrame <= anim->maxFrame; currentFrame++) {
+ anim->frameOffsets[currentFrame] = readS.pos();
magic = readS.readByte();
+ if (magic == SAGA_FRAME_END) {
+ if (currentFrame != anim->maxFrame) {
+ error("currentFrame != anim->maxFrame");
+ }
+ break;
+ }
if (magic != SAGA_FRAME_START) {
- // Frame sync failure. Magic Number not found
- return FAILURE;
+ error("Frame sync failure. Magic Number not found");
}
// skip header
- for (i = 0; i < SAGA_FRAME_HEADER_LEN; i++)
- readS.readByte();
-
+ readS.seek(SAGA_FRAME_HEADER_LEN, SEEK_CUR);
// For some strange reason, the animation header is in little
// endian format, but the actual RLE encoded frame data,
@@ -922,32 +801,27 @@ int Anim::getFrameOffset(const byte *resdata, size_t resdata_len, uint16 find_fr
continue;
break;
default:
- // Encountered unknown RLE marker, abort
- return FAILURE;
+ error("Encountered unknown RLE marker");
break;
}
} while (mark_byte != SAGA_FRAME_END);
}
-
- *frame_offset_p = readS.pos();
- return SUCCESS;
}
void Anim::animInfo() {
- uint16 anim_ct;
+ uint16 animCount;
uint16 i;
- uint16 idx;
- anim_ct = _anim_count;
+ animCount = getAnimationCount();
- _vm->_console->DebugPrintf("There are %d animations loaded:\n", anim_ct);
+ _vm->_console->DebugPrintf("There are %d animations loaded:\n", animCount);
- for (idx = 0, i = 0; i < anim_ct; idx++, i++) {
- while (_anim_tbl[idx] == NULL) {
- idx++;
+ for (i = 0; i < MAX_ANIMATIONS; i++) {
+ if (_animations[i] == NULL) {
+ break;
}
- _vm->_console->DebugPrintf("%02d: Frames: %u Flags: %u\n", i, _anim_tbl[idx]->maxframe, _anim_tbl[idx]->flags);
+ _vm->_console->DebugPrintf("%02d: Frames: %u Flags: %u\n", i, _animations[i]->maxFrame, _animations[i]->flags);
}
}
diff --git a/saga/animation.h b/saga/animation.h
index 2c8b0abc6d..ca6c027f73 100644
--- a/saga/animation.h
+++ b/saga/animation.h
@@ -48,58 +48,67 @@ namespace Saga {
// All animation resources begin with an ANIMATION_HEADER
// at 0x00, followed by a RLE code stream
-struct ANIMATION_HEADER {
- uint16 magic;
-
- uint16 screen_w;
- uint16 screen_h;
-
- byte unknown06;
- byte unknown07;
-
- byte maxframe;
- byte loopframe;
-
- uint16 start;
-};
-
struct FRAME_HEADER {
- int x_start;
- int y_start;
+ int xStart;
+ int yStart;
- int x_pos;
- int y_pos;
+ int xPos;
+ int yPos;
int width;
int height;
};
+enum AnimationState {
+ ANIM_PLAYING = 0x01,
+ ANIM_PAUSE = 0x02,
+ ANIM_STOPPING = 0x04,
+ ANIM_ENDSCENE = 0x80 // When animation ends, dispatch scene end event
+};
+
// Animation info array member
-struct ANIMATION {
+struct AnimationData {
+ byte *resourceData;
+ size_t resourceLength;
- const byte *resdata;
- size_t resdata_len;
+ uint16 magic;
+
+ uint16 screenWidth;
+ uint16 screenHeight;
+
+ byte unknown06;
+ byte unknown07;
+
+ uint16 maxFrame;
+ uint16 loopFrame;
+
+ uint16 start;
+
+ uint16 currentFrame;
+ size_t *frameOffsets;
- uint16 maxframe;
- size_t *frame_offsets;
- int16 current_frame;
uint16 completed;
uint16 cycles;
- int16 loopframe;
+
const byte *cur_frame_p;
size_t cur_frame_len;
- int frame_time;
- int state;
- int16 link_id;
+ int frameTime;
+
+ AnimationState state;
+ int16 linkId;
uint16 flags;
-};
-enum ANIM_FLAGS {
- ANIM_PLAYING = 0x01,
- ANIM_PAUSE = 0x02,
- ANIM_STOPPING = 0x04,
- ANIM_ENDSCENE = 0x80 // When animation ends, dispatch scene end event
+ AnimationData(const byte *animResourceData, size_t animResourceLength) {
+ memset(this, 0, sizeof(*this));
+ resourceLength = animResourceLength;
+ resourceData = (byte*)malloc(animResourceLength);
+ memcpy(resourceData, animResourceData, animResourceLength);
+ }
+ ~AnimationData() {
+ free(frameOffsets);
+ free(resourceData);
+ }
};
class Anim {
@@ -107,38 +116,56 @@ public:
Anim(SagaEngine *vm);
~Anim(void);
- int load(const byte *anim_resdata, size_t anim_resdata_len, uint16 *anim_id_p);
+ uint16 load(const byte *animResourceData, size_t animResourceLength);
void freeId(uint16 animId);
- int play(uint16 anim_id, int vector_time, bool playing = true);
- int link(int16 anim_id1, int16 anim_id2);
- int setFlag(uint16 anim_id, uint16 flag);
- int clearFlag(uint16 anim_id, uint16 flag);
- int setFrameTime(uint16 anim_id, int time);
- int reset(void);
+ void play(uint16 animId, int vectorTime, bool playing = true);
+ void link(int16 animId1, int16 animId2);
+ void setFlag(uint16 animId, uint16 flag);
+ void clearFlag(uint16 animId, uint16 flag);
+ void setFrameTime(uint16 animId, int time);
+ void reset(void);
void animInfo(void);
- void setCycles(uint animId, int cycles);
+ void setCycles(uint16 animId, int cycles);
void stop(uint16 animId);
void finish(uint16 animId);
void resume(uint16 animId, int cycles);
- int16 getCurrentFrame(uint16 anim_id);
+ int16 getCurrentFrame(uint16 animId);
private:
- int ITE_DecodeFrame(const byte *anim_resource, size_t anim_resource_len, size_t frame_offset, byte *buf, size_t buf_len);
+ void ITE_DecodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_t bufLength);
int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_p,
size_t thisf_len, const byte **nextf_p, size_t *nextf_len);
- int getFrameOffset(const byte *anim_resource, size_t anim_resource_len, uint16 find_frame, size_t *frame_offset);
- void readAnimHeader(MemoryReadStreamEndian &readS, ANIMATION_HEADER &ah);
+ void fillFrameOffsets(AnimationData *anim);
+
+ void validateAnimationId(uint16 animId) {
+ if (animId >= MAX_ANIMATIONS) {
+ error("validateAnimationId: animId out of range");
+ }
+ if (_animations[animId] == NULL) {
+ error("validateAnimationId: animId=%i unassigned", animId);
+ }
+ }
+
+ AnimationData* getAnimation(uint16 animId) {
+ validateAnimationId(animId);
+ return _animations[animId];
+ }
+
+ uint16 getAnimationCount() const {
+ uint16 i = 0;
+ for (; i < MAX_ANIMATIONS; i++) {
+ if (_animations[i] == NULL) {
+ break;
+ }
+ }
+ return i;
+ }
SagaEngine *_vm;
- bool _initialized;
-
- uint16 _anim_count;
- uint16 _anim_limit;
- ANIMATION *_anim_tbl[MAX_ANIMATIONS];
+ AnimationData *_animations[MAX_ANIMATIONS];
};
} // End of namespace Saga
#endif /* ANIMATION_H_ */
-/* end "r_animation.h" */
diff --git a/saga/scene.cpp b/saga/scene.cpp
index 777b399a79..b67510a128 100644
--- a/saga/scene.cpp
+++ b/saga/scene.cpp
@@ -718,25 +718,24 @@ int Scene::loadSceneResourceList(uint32 reslist_rn) {
}
int Scene::processSceneResources() {
- const byte *res_data;
- size_t res_data_len;
+ byte *resourceData;
+ size_t resourceDataLength;
const byte *pal_p;
int i;
// Process the scene resource list
for (i = 0; i < _resListEntries; i++) {
- res_data = _resList[i].res_data;
- res_data_len = _resList[i].res_data_len;
+ resourceData = _resList[i].res_data;
+ resourceDataLength = _resList[i].res_data_len;
switch (_resList[i].res_type) {
case SAGA_BG_IMAGE: // Scene background resource
if (_bg.loaded) {
- warning("Scene::processSceneResources(): Multiple background resources encountered");
- return FAILURE;
+ error("Scene::processSceneResources(): Multiple background resources encountered");
}
debug(0, "Loading background resource.");
- _bg.res_buf = _resList[i].res_data;
- _bg.res_len = _resList[i].res_data_len;
+ _bg.res_buf = resourceData;
+ _bg.res_len = resourceDataLength;
_bg.loaded = 1;
if (_vm->decodeBGImage(_bg.res_buf,
@@ -754,11 +753,11 @@ int Scene::processSceneResources() {
break;
case SAGA_BG_MASK: // Scene background mask resource
if (_bgMask.loaded) {
- warning("Scene::ProcessSceneResources(): Duplicate background mask resource encountered");
+ error("Scene::ProcessSceneResources(): Duplicate background mask resource encountered");
}
debug(0, "Loading BACKGROUND MASK resource.");
- _bgMask.res_buf = _resList[i].res_data;
- _bgMask.res_len = _resList[i].res_data_len;
+ _bgMask.res_buf = resourceData;
+ _bgMask.res_len = resourceDataLength;
_bgMask.loaded = 1;
_vm->decodeBGImage(_bgMask.res_buf, _bgMask.res_len, &_bgMask.buf,
&_bgMask.buf_len, &_bgMask.w, &_bgMask.h);
@@ -766,15 +765,15 @@ int Scene::processSceneResources() {
break;
case SAGA_STRINGS:
debug(0, "Loading scene strings resource...");
- _vm->loadStrings(_sceneStrings, _resList[i].res_data, _resList[i].res_data_len);
+ _vm->loadStrings(_sceneStrings, resourceData, resourceDataLength);
break;
case SAGA_OBJECT_MAP:
debug(0, "Loading object map resource...");
- _objectMap->load(res_data, res_data_len);
+ _objectMap->load(resourceData, resourceDataLength);
break;
case SAGA_ACTION_MAP:
debug(0, "Loading action map resource...");
- _actionMap->load(res_data, res_data_len);
+ _actionMap->load(resourceData, resourceDataLength);
break;
case SAGA_ISO_IMAGES:
if (!(_sceneDescription.flags & kSceneFlagISO)) {
@@ -783,7 +782,7 @@ int Scene::processSceneResources() {
debug(0, "Loading isometric images resource.");
- _vm->_isoMap->loadImages(res_data, res_data_len);
+ _vm->_isoMap->loadImages(resourceData, resourceDataLength);
break;
case SAGA_ISO_MAP:
if (!(_sceneDescription.flags & kSceneFlagISO)) {
@@ -792,7 +791,7 @@ int Scene::processSceneResources() {
debug(0, "Loading isometric map resource.");
- _vm->_isoMap->loadMap(res_data, res_data_len);
+ _vm->_isoMap->loadMap(resourceData, resourceDataLength);
break;
case SAGA_ISO_PLATFORMS:
if (!(_sceneDescription.flags & kSceneFlagISO)) {
@@ -801,7 +800,7 @@ int Scene::processSceneResources() {
debug(0, "Loading isometric platforms resource.");
- _vm->_isoMap->loadPlatforms(res_data, res_data_len);
+ _vm->_isoMap->loadPlatforms(resourceData, resourceDataLength);
break;
case SAGA_ISO_METATILES:
if (!(_sceneDescription.flags & kSceneFlagISO)) {
@@ -810,7 +809,7 @@ int Scene::processSceneResources() {
debug(0, "Loading isometric metatiles resource.");
- _vm->_isoMap->loadMetaTiles(res_data, res_data_len);
+ _vm->_isoMap->loadMetaTiles(resourceData, resourceDataLength);
break;
case SAGA_ANIM_1:
case SAGA_ANIM_2:
@@ -820,21 +819,17 @@ int Scene::processSceneResources() {
case SAGA_ANIM_6:
case SAGA_ANIM_7:
{
- uint16 new_anim_id;
+ uint16 animId;
debug(0, "Loading animation resource...");
- 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;
- }
+ animId = _vm->_anim->load(resourceData, resourceDataLength);
SCENE_ANIMINFO *new_animinfo;
new_animinfo = _animList.pushBack().operator->();
- new_animinfo->anim_handle = new_anim_id;
+ new_animinfo->anim_handle = animId;
new_animinfo->anim_res_number = _resList[i].res_number;
_animEntries++;
}
@@ -846,15 +841,15 @@ int Scene::processSceneResources() {
debug(0, "Loading isometric multi resource.");
- _vm->_isoMap->loadMulti(res_data, res_data_len);
+ _vm->_isoMap->loadMulti(resourceData, resourceDataLength);
break;
case SAGA_PAL_ANIM:
debug(0, "Loading palette animation resource.");
- _vm->_palanim->loadPalAnim(_resList[i].res_data, _resList[i].res_data_len);
+ _vm->_palanim->loadPalAnim(resourceData, resourceDataLength);
break;
case SAGA_ENTRY:
debug(0, "Loading entry list resource...");
- loadSceneEntryList(res_data, res_data_len);
+ loadSceneEntryList(resourceData, resourceDataLength);
break;
case SAGA_FACES:
_vm->_interface->loadScenePortraits(_resList[i].res_number);
@@ -889,6 +884,8 @@ void Scene::draw() {
}
void Scene::endScene() {
+ int i;
+
if (!_sceneLoaded)
return;
@@ -921,8 +918,11 @@ void Scene::endScene() {
}
// Free scene resource list
- if (_loadDescription) {
+ for (i = 0; i < _resListEntries; i++) {
+ RSC_FreeResource(_resList[i].res_data);
+ }
+ if (_loadDescription) {
free(_resList);
}