aboutsummaryrefslogtreecommitdiff
path: root/saga
diff options
context:
space:
mode:
authorAndrew Kurushin2005-01-09 15:07:49 +0000
committerAndrew Kurushin2005-01-09 15:07:49 +0000
commitf3b8221dd6a06f486a15aeedfd26d054a9287a18 (patch)
tree968883fa94ea6de63d1af9fb10ba2479f1ef27df /saga
parent9d1f4ff1e6ea637518f9778b863db5bdb8683658 (diff)
downloadscummvm-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.cpp33
-rw-r--r--saga/actor.h3
-rw-r--r--saga/actordata.cpp11
-rw-r--r--saga/interface.cpp22
-rw-r--r--saga/interface.h8
-rw-r--r--saga/sprite.cpp404
-rw-r--r--saga/sprite.h55
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;