diff options
author | Andrew Kurushin | 2005-01-09 15:07:49 +0000 |
---|---|---|
committer | Andrew Kurushin | 2005-01-09 15:07:49 +0000 |
commit | f3b8221dd6a06f486a15aeedfd26d054a9287a18 (patch) | |
tree | 968883fa94ea6de63d1af9fb10ba2479f1ef27df /saga | |
parent | 9d1f4ff1e6ea637518f9778b863db5bdb8683658 (diff) | |
download | scummvm-rg350-f3b8221dd6a06f486a15aeedfd26d054a9287a18.tar.gz scummvm-rg350-f3b8221dd6a06f486a15aeedfd26d054a9287a18.tar.bz2 scummvm-rg350-f3b8221dd6a06f486a15aeedfd26d054a9287a18.zip |
rewritten sprite class
- sprites decoded on first load
- some speed optimization
- actors uses kExtended flag to append spriteList
svn-id: r16497
Diffstat (limited to 'saga')
-rw-r--r-- | saga/actor.cpp | 33 | ||||
-rw-r--r-- | saga/actor.h | 3 | ||||
-rw-r--r-- | saga/actordata.cpp | 11 | ||||
-rw-r--r-- | saga/interface.cpp | 22 | ||||
-rw-r--r-- | saga/interface.h | 8 | ||||
-rw-r--r-- | saga/sprite.cpp | 404 | ||||
-rw-r--r-- | saga/sprite.h | 55 |
7 files changed, 229 insertions, 307 deletions
diff --git a/saga/actor.cpp b/saga/actor.cpp index 3436969a75..9cb77324d5 100644 --- a/saga/actor.cpp +++ b/saga/actor.cpp @@ -228,7 +228,7 @@ Actor::~Actor() { for (i = 0; i < ACTORCOUNT; i++) { actor = &_actors[i]; free(actor->frames); - _vm->_sprite->freeSprite(actor->spriteList); + actor->spriteList.freeMem(); } } @@ -239,6 +239,7 @@ bool Actor::loadActorResources(ActorData *actor) { ActorFrameSequence *framesPointer; int lastFrame; int i, orient; + int resourceId; if (actor->frameListResourceId == 0) { warning("Frame List ID = 0 for actor index %d", actor->index); @@ -281,20 +282,22 @@ bool Actor::loadActorResources(ActorData *actor) { actor->frames = framesPointer; actor->framesCount = framesCount; - - debug(9, "Loading sprite resource id %d", actor->spriteListResourceId); - if (_vm->_sprite->loadList(actor->spriteListResourceId, &actor->spriteList) != SUCCESS) { + resourceId = actor->spriteListResourceId; + debug(9, "Loading sprite resource id %d", resourceId); + if (_vm->_sprite->loadList(resourceId, actor->spriteList) != SUCCESS) { warning("Unable to load sprite list"); return false; } - i = _vm->_sprite->getListLen(actor->spriteList); - - if (lastFrame >= i) { - debug(9, "Appending to sprite list %d (+ %d)", actor->spriteListResourceId, lastFrame); - if (_vm->_sprite->appendList(actor->spriteListResourceId + 1, actor->spriteList) != SUCCESS) { - warning("Unable append sprite list"); - return false; + i = actor->spriteList.spriteCount; + if ((actor->flags & kExtended)) { + while ((lastFrame >= actor->spriteList.spriteCount)) { + resourceId++; + debug(9, "Appending to sprite list %d", resourceId); + if (_vm->_sprite->loadList(resourceId, actor->spriteList) != SUCCESS) { + warning("Unable append sprite list"); + return false; + } } } @@ -942,13 +945,13 @@ int Actor::drawActors() { continue; } frameNumber = 8; - spriteList = _vm->_sprite->_mainSprites; + spriteList = &_vm->_sprite->_mainSprites; } else { frameNumber = actor->frameNumber; - spriteList = actor->spriteList; + spriteList = &actor->spriteList; } - if ((frameNumber < 0) || (spriteList->sprite_count <= frameNumber)) { + if ((frameNumber < 0) || (spriteList->spriteCount <= frameNumber)) { warning("Actor::drawActors frameNumber invalid for actorId 0x%X", actor->actorId); continue; } @@ -956,7 +959,7 @@ int Actor::drawActors() { if (_vm->_scene->getFlags() & kSceneFlagISO) { //todo: it } else { - _vm->_sprite->drawOccluded(back_buf, spriteList, frameNumber, actor->screenPosition, actor->screenScale, actor->screenDepth); + _vm->_sprite->drawOccluded(back_buf, *spriteList, frameNumber, actor->screenPosition, actor->screenScale, actor->screenDepth); } } diff --git a/saga/actor.h b/saga/actor.h index 49b8446f55..5c6b47b0cd 100644 --- a/saga/actor.h +++ b/saga/actor.h @@ -198,7 +198,7 @@ struct ActorData { uint8 cycleTimeCount; uint8 cycleFlags; - SpriteList *spriteList; // Actor's sprite list data + SpriteList spriteList; // Actor's sprite list data int spriteListResourceId; // Actor's sprite list resource id ActorFrameSequence *frames; // Actor's frames @@ -232,6 +232,7 @@ struct ActorData { memset(this, 0xFE, sizeof(*this)); walkStepsPoints = NULL; walkStepsAlloced = walkStepsCount = walkStepIndex = 0; + memset(&spriteList, 0, sizeof(spriteList)); } ~ActorData() { free(walkStepsPoints); diff --git a/saga/actordata.cpp b/saga/actordata.cpp index 335a42d845..ec6c52a3dc 100644 --- a/saga/actordata.cpp +++ b/saga/actordata.cpp @@ -34,10 +34,13 @@ ActorTableData ActorTable[ACTORCOUNT] = { // flags name scene x y z spr frm scp col // ------------ ---- ---- ---- ----- ---- ---- ---- --- ---- -- -- -- - { kProtagonist, 0, 1, 0, 0, 0, 37, 135, 0, 1, 0, 0, 0}, // map party - // spr and frm numbers taken from permanent actors list - { kFollower, 1, 0, 0, 0, 0, 45, 177, 1, 132, 0, 0, 0}, // Okk - { kFollower, 2, 0, 0, 0, 0, 48, 143, 2, 161, 0, 0, 0}, // Eeah + { kProtagonist | kExtended, + 0, 1, 0, 0, 0, 37, 135, 0, 1, 0, 0, 0}, // map party + // spr and frm numbers taken from permanent actors list + { kFollower | kExtended, + 1, 0, 0, 0, 0, 45, 177, 1, 132, 0, 0, 0}, // Okk + { kFollower | kExtended, + 2, 0, 0, 0, 0, 48, 143, 2, 161, 0, 0, 0}, // Eeah { 0, 3, 0, 240, 480, 0, 115, 206, 0, 25, 0, 0, 0}, // albino ferret { 0, 4, 17, 368, 400, 0, 115, 206, 4, 49, 0, 0, 0}, // moneychanger { 0, 5, 11, 552, 412, 0, 54, 152, 1, 171, 0, 0, 0}, // Sist diff --git a/saga/interface.cpp b/saga/interface.cpp index 05e7afe96e..57318d8785 100644 --- a/saga/interface.cpp +++ b/saga/interface.cpp @@ -213,9 +213,15 @@ Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) { return; } - _vm->_sprite->loadList(RID_ITE_COMMAND_BUTTONSPRITES, &_cPanel.sprites); + if (_vm->_sprite->loadList(RID_ITE_COMMAND_BUTTONSPRITES, _cPanel.sprites) != SUCCESS) { + error("Unable to load sprite list"); + } + + + if (_vm->_sprite->loadList(RID_ITE_DEFAULT_PORTRAITS, _defPortraits) != SUCCESS) { + error("Unable to load sprite list"); + } - _vm->_sprite->loadList(RID_ITE_DEFAULT_PORTRAITS, &_defPortraits); _vm->decodeBGImage(_cPanel.res, _cPanel.res_len, &_cPanel.img, &_cPanel.img_len, &_cPanel.img_w, &_cPanel.img_h); @@ -231,7 +237,6 @@ Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) { _dPanel.y = 149; _cPanel.set_button = COMMAND_DEFAULT_BUTTON; - _scenePortraits = 0; _leftPortrait = 0; _rightPortrait = 0; @@ -256,6 +261,10 @@ Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) { Interface::~Interface(void) { free(_inventory); + + _cPanel.sprites.freeMem(); + _defPortraits.freeMem(); + _scenePortraits.freeMem(); _initialized = false; } @@ -332,11 +341,10 @@ int Interface::setStatusText(const char *new_txt) { return SUCCESS; } -int Interface::loadScenePortraits(int res) { - if (_scenePortraits) - _vm->_sprite->freeSprite(_scenePortraits); +int Interface::loadScenePortraits(int resourceId) { + _scenePortraits.freeMem(); - return _vm->_sprite->loadList(res, &_scenePortraits); + return _vm->_sprite->loadList(resourceId, _scenePortraits); } int Interface::setLeftPortrait(int portrait) { diff --git a/saga/interface.h b/saga/interface.h index 28f648c7bf..313954fce2 100644 --- a/saga/interface.h +++ b/saga/interface.h @@ -150,7 +150,7 @@ struct INTERFACE_PANEL { int set_button; int nbuttons; INTERFACE_BUTTON *buttons; - SpriteList *sprites; + SpriteList sprites; }; struct INTERFACE_DESC { @@ -217,7 +217,7 @@ public: void unlockMode() { _panelMode = _lockedMode; } bool isInMainMode() { return _inMainMode; } int setStatusText(const char *new_txt); - int loadScenePortraits(int res); + int loadScenePortraits(int resourceId); int setLeftPortrait(int portrait); int setRightPortrait(int portrait); int draw(); @@ -252,8 +252,8 @@ private: char _statusText[STATUS_TEXT_LEN]; int _leftPortrait; int _rightPortrait; - SpriteList *_defPortraits; - SpriteList *_scenePortraits; + SpriteList _defPortraits; + SpriteList _scenePortraits; int _activeVerb; SCRIPT_THREAD *_iThread; diff --git a/saga/sprite.cpp b/saga/sprite.cpp index 940ea56a62..74fc020492 100644 --- a/saga/sprite.cpp +++ b/saga/sprite.cpp @@ -47,12 +47,12 @@ Sprite::Sprite(SagaEngine *vm) : _vm(vm), _initialized(false) { _decodeBufLen = DECODE_BUF_LEN; - _decodeBuf = (byte *)malloc(DECODE_BUF_LEN); + _decodeBuf = (byte *)malloc(_decodeBufLen); if (_decodeBuf == NULL) { return; } - loadList(RID_ITE_MAIN_SPRITES, &_mainSprites); //fixme: IHNM may have no such list + loadList(RID_ITE_MAIN_SPRITES, _mainSprites); //fixme: IHNM may have no such list _initialized = true; } @@ -63,231 +63,185 @@ Sprite::~Sprite(void) { } debug(0, "Shutting down sprite subsystem..."); - + _mainSprites.freeMem(); free(_decodeBuf); } -int Sprite::loadList(int resource_num, SpriteList **sprite_list_p) { - SpriteList *new_slist; - byte *spritelist_data; - size_t spritelist_len; - uint16 sprite_count; - uint16 i; +int Sprite::loadList(int resourceId, SpriteList &spriteList) { + SpriteInfo *spriteInfo; + byte *spriteListData; + size_t spriteListLength; + uint16 oldSpriteCount; + uint16 newSpriteCount; + uint16 spriteCount; + int i; + int outputLength; + uint32 offset; + const byte *spritePointer; + const byte *spriteDataPointer; - if (RSC_LoadResource(_spriteContext, resource_num, &spritelist_data, &spritelist_len) != SUCCESS) { + if (RSC_LoadResource(_spriteContext, resourceId, &spriteListData, &spriteListLength) != SUCCESS) { + warning("Sprite::loadList RSC_LoadResource FAILURE"); return FAILURE; } - if (spritelist_len == 0) + if (spriteListLength == 0) { + warning("Sprite::loadList spriteListLength == 0"); return FAILURE; - - MemoryReadStreamEndian readS(spritelist_data, spritelist_len, IS_BIG_ENDIAN); - - sprite_count = readS.readUint16(); - - new_slist = (SpriteList *)malloc(sizeof(*new_slist)); - if (new_slist == NULL) { - return MEM; } - new_slist->sprite_count = sprite_count; + MemoryReadStreamEndian readS(spriteListData, spriteListLength, IS_BIG_ENDIAN); - new_slist->offset_list = (SPRITELIST_OFFSET *)malloc(sprite_count * sizeof(*new_slist->offset_list)); - if (new_slist->offset_list == NULL) { - free(new_slist); - return MEM; - } - - for (i = 0; i < sprite_count; i++) { - new_slist->offset_list[i].data_idx = 0; - if (_vm->_features & GF_MAC_RESOURCES) - new_slist->offset_list[i].offset = readS.readUint32(); - else - new_slist->offset_list[i].offset = readS.readUint16(); - } + spriteCount = readS.readUint16(); - new_slist->slist_rn = resource_num; - new_slist->sprite_data[0] = spritelist_data; - new_slist->append_count = 0; + oldSpriteCount = spriteList.spriteCount; + newSpriteCount = spriteList.spriteCount + spriteCount; - *sprite_list_p = new_slist; - - return SUCCESS; -} - -int Sprite::appendList(int resource_num, SpriteList *spritelist) { - byte *spritelist_data; - size_t spritelist_len; - void *test_p; - uint16 old_sprite_count; - uint16 new_sprite_count; - uint16 sprite_count; - int i; - - if (spritelist->append_count >= (APPENDMAX - 1)) { - return FAILURE; + spriteList.infoList = (SpriteInfo *)realloc(spriteList.infoList, newSpriteCount * sizeof(*spriteList.infoList)); + if (spriteList.infoList == NULL) { + error("Sprite::loadList Not enough memory"); } - if (RSC_LoadResource(_spriteContext, resource_num, &spritelist_data, &spritelist_len) != SUCCESS) { - return FAILURE; - } + spriteList.spriteCount = newSpriteCount; - MemoryReadStreamEndian readS(spritelist_data, spritelist_len, IS_BIG_ENDIAN); + for (i = oldSpriteCount; i < spriteList.spriteCount; i++) { + spriteInfo = &spriteList.infoList[i]; + if (_vm->_features & GF_MAC_RESOURCES) + offset = readS.readUint32(); + else + offset = readS.readUint16(); - sprite_count = readS.readUint16(); + if (offset >= spriteListLength) { + error("Sprite::loadList offset exceed"); + } - old_sprite_count = spritelist->sprite_count; - new_sprite_count = spritelist->sprite_count + sprite_count; + spritePointer = spriteListData; + spritePointer += offset; - test_p = realloc(spritelist->offset_list, new_sprite_count * sizeof(*spritelist->offset_list)); - if (test_p == NULL) { - return MEM; - } + MemoryReadStream readS(spritePointer, (_vm->_features & GF_MAC_RESOURCES) ? 8 : 4); - spritelist->offset_list = (SPRITELIST_OFFSET *)test_p; + if (!(_vm->_features & GF_MAC_RESOURCES)) { + spriteInfo->xAlign = readS.readSByte(); + spriteInfo->yAlign = readS.readSByte(); - spritelist->sprite_count = new_sprite_count; - spritelist->append_count++; + spriteInfo->width = readS.readByte(); + spriteInfo->height = readS.readByte(); + } else { + spriteInfo->xAlign = readS.readSint16BE(); + spriteInfo->yAlign = readS.readSint16BE(); - 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.readUint16(); + spriteInfo->width = readS.readUint16BE(); + spriteInfo->height = readS.readUint16BE(); + } + spriteDataPointer = spritePointer + readS.pos(); + outputLength = spriteInfo->width * spriteInfo->height; + decodeRLEBuffer(spriteDataPointer, 64000, outputLength); //todo: 64000 - should be replace by real input length + spriteInfo->decodedBuffer = (byte *) malloc(outputLength); + if (spriteInfo->decodedBuffer == NULL) { + error("Sprite::loadList Not enough memory"); + } + memcpy(spriteInfo->decodedBuffer, _decodeBuf, outputLength); } - spritelist->sprite_data[spritelist->append_count] = spritelist_data; + RSC_FreeResource(spriteListData); return SUCCESS; } -int Sprite::getListLen(SpriteList *spritelist) { - return spritelist->sprite_count; -} - -int Sprite::freeSprite(SpriteList *spritelist) { - int i; - - for (i = 0; i <= spritelist->append_count; i++) { - - RSC_FreeResource(spritelist->sprite_data[i]); +void Sprite::getScaledSpriteBuffer(SpriteList &spriteList, int spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer) { + SpriteInfo *spriteInfo; + assert(spriteList.spriteCount>spriteNumber); + spriteInfo = &spriteList.infoList[spriteNumber]; + + if (scale < 256) { + xAlign = (spriteInfo->xAlign * scale) >> 8; + yAlign = (spriteInfo->yAlign * scale) >> 8; + height = (spriteInfo->height * scale + 0x80) >> 8; + width = (spriteInfo->width * scale + 0x80) >> 8; + scaleBuffer(spriteInfo->decodedBuffer, spriteInfo->width, spriteInfo->height, scale); + buffer = _decodeBuf; + } else { + xAlign = spriteInfo->xAlign; + yAlign = spriteInfo->yAlign; + height = spriteInfo->height; + width = spriteInfo->width; + buffer = spriteInfo->decodedBuffer; } - free(spritelist->offset_list); - free(spritelist); - - return SUCCESS; } -int Sprite::draw(SURFACE *ds, SpriteList *sprite_list, int sprite_num, const Point &screenCoord, int scale) { - int offset; - int offset_idx; - byte *sprite_p; - const byte *sprite_data_p; +int Sprite::draw(SURFACE *ds, SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale) { + const byte *spriteBuffer; int i, j; byte *buf_row_p; - byte *src_row_p; - int s_width, so_width; - int s_height, so_height; + const byte *src_row_p; int clip_width; int clip_height; - int x_align; - int y_align; - Point spr_pt; - - if (!_initialized) { - return FAILURE; - } - - offset = sprite_list->offset_list[sprite_num].offset; - offset_idx = sprite_list->offset_list[sprite_num].data_idx; - - sprite_p = sprite_list->sprite_data[offset_idx]; - sprite_p += offset; - - assert(sprite_p); - - MemoryReadStream readS(sprite_p, 8); - if (!(_vm->_features & GF_MAC_RESOURCES)) { - x_align = readS.readSByte(); - y_align = readS.readSByte(); - - so_width = s_width = readS.readByte(); - so_height = s_height = readS.readByte(); - } else { - x_align = readS.readSint16BE(); - y_align = readS.readSint16BE(); - - so_width = s_width = readS.readUint16BE(); - so_height = s_height = readS.readUint16BE(); - } - spr_pt.x = screenCoord.x + x_align; - spr_pt.y = screenCoord.y + y_align; - - if (scale < 256) - scaleSpriteCoords(scale, &s_width, &s_height, &x_align, &y_align); + int width; + int height; + int xAlign; + int yAlign; + Point spritePointer; - sprite_data_p = sprite_p + readS.pos(); + assert(_initialized); - decodeRLESprite(sprite_data_p, 64000, _decodeBuf, so_width * so_height); + getScaledSpriteBuffer(spriteList, spriteNumber, scale, width, height, xAlign, yAlign, spriteBuffer); + + spritePointer.x = screenCoord.x + xAlign; + spritePointer.y = screenCoord.y + yAlign; - if (scale < 256) - scaleSprite(_decodeBuf, so_width, so_height, scale); - - if (spr_pt.x < 0) { + if (spritePointer.x < 0) { return 0; } - - if (spr_pt.y < 0) { + if (spritePointer.y < 0) { return 0; } - buf_row_p = (byte *)ds->pixels + ds->pitch * spr_pt.y; - src_row_p = _decodeBuf; + buf_row_p = (byte *)ds->pixels + ds->pitch * spritePointer.y; + src_row_p = spriteBuffer; // Clip to right side of surface - clip_width = s_width; - if (s_width > (ds->w - spr_pt.x)) { - clip_width = (ds->w - spr_pt.x); + clip_width = width; + if (width > (ds->w - spritePointer.x)) { + clip_width = (ds->w - spritePointer.x); } // Clip to bottom side of surface - clip_height = s_height; - if (s_height > (ds->h - spr_pt.y)) { - clip_height = (ds->h - spr_pt.y); + clip_height = height; + if (height > (ds->h - spritePointer.y)) { + clip_height = (ds->h - spritePointer.y); } for (i = 0; i < clip_height; i++) { for (j = 0; j < clip_width; j++) { if (*(src_row_p + j) != 0) { - *(buf_row_p + j + spr_pt.x) = *(src_row_p + j); + *(buf_row_p + j + spritePointer.x) = *(src_row_p + j); } } buf_row_p += ds->pitch; - src_row_p += s_width; + src_row_p += width; } return SUCCESS; } -int Sprite::drawOccluded(SURFACE *ds, SpriteList *sprite_list, int sprite_num, const Point &screenCoord, int scale, int depth) { - int offset; - int offset_idx; - byte *sprite_p; - const byte *sprite_data_p; +int Sprite::drawOccluded(SURFACE *ds, SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, int depth) { + const byte *spriteBuffer; int x, y; byte *dst_row_p; - byte *src_row_p; - byte *src_p; + const byte *src_row_p; + const byte *src_p; byte *dst_p; byte *mask_p; - int s_width, so_width; - int s_height, so_height; - int x_align; - int y_align; + int width; + int height; + int xAlign; + int yAlign; + Point spritePointer; // Clipinfo variables - Point spr_pt; - Rect spr_src_rect; - Rect spr_dst_rect; + Rect spriteSourceRect; + Rect spriteDestRect; CLIPINFO ci; // BG mask variables @@ -299,67 +253,32 @@ int Sprite::drawOccluded(SURFACE *ds, SpriteList *sprite_list, int sprite_num, c int mask_z; - if (!_initialized) { - return FAILURE; - } + assert(_initialized); if (!_vm->_scene->isBGMaskPresent()) { - return draw(ds, sprite_list, sprite_num, screenCoord, scale); + return draw(ds, spriteList, spriteNumber, screenCoord, scale); } - if (sprite_num >= sprite_list->sprite_count) { - warning("Invalid sprite number (%d) for sprite list %d", sprite_num, sprite_list->slist_rn); - return FAILURE; - } - - // Get sprite data from list - offset = sprite_list->offset_list[sprite_num].offset; - offset_idx = sprite_list->offset_list[sprite_num].data_idx; - - sprite_p = sprite_list->sprite_data[offset_idx]; - sprite_p += offset; - - MemoryReadStream readS(sprite_p, 8); - - // Read sprite dimensions -- should probably cache this stuff in - // sprite list - if (!(_vm->_features & GF_MAC_RESOURCES)) { - x_align = readS.readSByte(); - y_align = readS.readSByte(); - - so_width = s_width = readS.readByte(); - so_height = s_height = readS.readByte(); - } else { - x_align = readS.readSint16BE(); - y_align = readS.readSint16BE(); - - so_width = s_width = readS.readUint16BE(); - so_height = s_height = readS.readUint16BE(); - } - - sprite_data_p = sprite_p + readS.pos(); - _vm->_scene->getBGMaskInfo(maskWidth, maskHeight, maskBuffer, maskBufferLength); - if (scale < 256) - scaleSpriteCoords(scale, &s_width, &s_height, &x_align, &y_align); - - spr_src_rect.left = 0; - spr_src_rect.top = 0; - spr_src_rect.right = s_width; - spr_src_rect.bottom = s_height; + getScaledSpriteBuffer(spriteList, spriteNumber, scale, width, height, xAlign, yAlign, spriteBuffer); - spr_dst_rect.left = 0; - spr_dst_rect.top = 0; - spr_dst_rect.right = ds->clip_rect.right; - spr_dst_rect.bottom = MIN(ds->clip_rect.bottom, (int16)maskHeight); + spritePointer.x = screenCoord.x + xAlign; + spritePointer.y = screenCoord.y + yAlign; - spr_pt.x = screenCoord.x + x_align; - spr_pt.y = screenCoord.y + y_align; + spriteSourceRect.left = 0; + spriteSourceRect.top = 0; + spriteSourceRect.right = width; + spriteSourceRect.bottom = height; - ci.dst_rect = &spr_dst_rect; - ci.src_rect = &spr_src_rect; - ci.dst_pt = &spr_pt; + spriteDestRect.left = 0; + spriteDestRect.top = 0; + spriteDestRect.right = ds->clip_rect.right; + spriteDestRect.bottom = MIN(ds->clip_rect.bottom, (int16)maskHeight); + + ci.dst_rect = &spriteDestRect; + ci.src_rect = &spriteSourceRect; + ci.dst_pt = &spritePointer; getClipInfo(&ci); @@ -367,13 +286,9 @@ int Sprite::drawOccluded(SURFACE *ds, SpriteList *sprite_list, int sprite_num, c return SUCCESS; } - decodeRLESprite(sprite_data_p, 64000, _decodeBuf, so_width * so_height); - - if (scale < 256) - scaleSprite(_decodeBuf, so_width, so_height, scale); // Finally, draw the occluded sprite - src_row_p = _decodeBuf + ci.src_draw_x + (ci.src_draw_y * s_width); + src_row_p = spriteBuffer + ci.src_draw_x + (ci.src_draw_y * width); dst_row_p = (byte *)ds->pixels + ci.dst_draw_x + (ci.dst_draw_y * ds->pitch); mask_row_p = maskBuffer + ci.dst_draw_x + (ci.dst_draw_y * maskWidth); @@ -395,59 +310,57 @@ int Sprite::drawOccluded(SURFACE *ds, SpriteList *sprite_list, int sprite_num, c } dst_row_p += ds->pitch; mask_row_p += maskWidth; - src_row_p += s_width; + src_row_p += width; } return SUCCESS; } -int Sprite::decodeRLESprite(const byte *inbuf, size_t inbuf_len, byte *outbuf, size_t outbuf_len) { +void Sprite::decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t outLength) { int bg_runcount; int fg_runcount; - byte *outbuf_ptr; - byte *outbuf_end; + byte *outPointer; + byte *outPointerEnd; int c; - outbuf_ptr = outbuf; - - outbuf_end = outbuf + outbuf_len; - outbuf_end--; + if (outLength > _decodeBufLen) { // TODO: may we should make dynamic growing? + error("Sprite::decodeRLEBuffer outLength > _decodeBufLen"); + } + + outPointer = _decodeBuf; + outPointerEnd = _decodeBuf + outLength; + outPointerEnd--; - memset(outbuf, 0, outbuf_len); + memset(outPointer, 0, outLength); - MemoryReadStream readS(inbuf, inbuf_len); + MemoryReadStream readS(inputBuffer, inLength); - while (!readS.eof() && (outbuf_ptr < outbuf_end)) { + while (!readS.eof() && (outPointer < outPointerEnd)) { bg_runcount = readS.readByte(); fg_runcount = readS.readByte(); for (c = 0; c < bg_runcount; c++) { - *outbuf_ptr = (byte) 0; - if (outbuf_ptr < outbuf_end) - outbuf_ptr++; + *outPointer = (byte) 0; + if (outPointer < outPointerEnd) + outPointer++; else - return 0; + return; } for (c = 0; c < fg_runcount; c++) { - *outbuf_ptr = readS.readByte(); - if (outbuf_ptr < outbuf_end) - outbuf_ptr++; + *outPointer = readS.readByte(); + if (outPointer < outPointerEnd) + outPointer++; else - return 0; + return; } } - - return SUCCESS; } -void Sprite::scaleSprite(byte *buf, int width, int height, int scale) { +void Sprite::scaleBuffer(const byte *src, int width, int height, int scale) { byte skip = 256 - scale; // skip factor - byte vskip = 0x80, hskip; - byte *src, *dst; - - src = dst = buf; + byte *dst = _decodeBuf; for (int i = 0; i < height; i++) { vskip += skip; @@ -468,12 +381,5 @@ void Sprite::scaleSprite(byte *buf, int width, int height, int scale) { } } -void Sprite::scaleSpriteCoords(int scale, int *width, int *height, int *x_align, int *y_align) { - *x_align = (*x_align * scale) >> 8; - *y_align = (*y_align * scale) >> 8; - *height = (*height * scale + 0x80) >> 8; - *width = (*width * scale + 0x80) >> 8; -} - } // End of namespace Saga diff --git a/saga/sprite.h b/saga/sprite.h index c1590db8a1..9f229891fb 100644 --- a/saga/sprite.h +++ b/saga/sprite.h @@ -28,53 +28,54 @@ namespace Saga { -#define APPENDMAX 4 - #define SPRITE_ZMAX 16 #define SPRITE_ZMASK 0x0F #define DECODE_BUF_LEN 64000 -struct SPRITELIST_ENTRY { - int x_align; - int y_align; +struct SpriteInfo { + byte *decodedBuffer; int width; int height; - -}; - -struct SPRITELIST_OFFSET { - uint16 data_idx; - uint32 offset; + int xAlign; + int yAlign; }; struct SpriteList { - int append_count; - int sprite_count; - SPRITELIST_OFFSET *offset_list; - int slist_rn; - byte *sprite_data[APPENDMAX]; + int spriteListResourceId; + int spriteCount; + SpriteInfo *infoList; + + void freeMem() { + int i; + for (i = 0; i < spriteCount; i++) { + free(infoList[i].decodedBuffer); + } + free(infoList); + memset(this, 0, sizeof(*this)); + } + + SpriteList() { + memset(this, 0, sizeof(*this)); + } }; class Sprite { public: - SpriteList *_mainSprites; + SpriteList _mainSprites; Sprite(SagaEngine *vm); ~Sprite(void); - int loadList(int resource_num, SpriteList **sprite_list_p); - int appendList(int resource_num, SpriteList *spritelist); - int getListLen(SpriteList *spritelist); - int freeSprite(SpriteList *spritelist); - int draw(SURFACE *ds, SpriteList *sprite_list, int sprite_num, const Point &screenCoord, int scale); - int drawOccluded(SURFACE *ds, SpriteList *sprite_list, int sprite_num, const Point &screenCoord, int scale, int depth); + int loadList(int resourceId, SpriteList &spriteList); // load or append spriteList + int draw(SURFACE *ds, SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale); + int drawOccluded(SURFACE *ds, SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, int depth); private: - int decodeRLESprite(const byte *inbuf, size_t inbuf_len, byte *outbuf, size_t outbuf_len); - void scaleSprite(byte *buf, int width, int height, int scale); - void scaleSpriteCoords(int scale, int *width, int *height, int *x_align, int *y_align); - + void decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t outLength); + void scaleBuffer(const byte *src, int width, int height, int scale); + void getScaledSpriteBuffer(SpriteList &spriteList, int spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer); + SagaEngine *_vm; bool _initialized; RSCFILE_CONTEXT *_spriteContext; |