Files
2026-02-02 04:50:13 +01:00

175 lines
4.5 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "asylum/system/graphics.h"
#include "asylum/asylum.h"
#include "asylum/respack.h"
namespace Asylum {
GraphicResource::GraphicResource(AsylumEngine *engine) : _vm(engine), _resourceId(kResourceNone) {
}
GraphicResource::GraphicResource(AsylumEngine *engine, ResourceId id) : _vm(engine), _resourceId(kResourceNone) {
if (!load(id))
error("[GraphicResource::GraphicResource] Error loading resource (0x%X)", id);
}
GraphicResource::~GraphicResource() {
clear();
}
bool GraphicResource::load(ResourceId id) {
if (id == kResourceNone)
error("[GraphicResource::load] Trying to load an invalid resource!");
// Clear previously loaded data
clear();
ResourceEntry *resEntry = getResource()->get(id);
if (!resEntry)
return false;
_resourceId = id;
init(resEntry->data, resEntry->size);
return true;
}
void GraphicResource::clear() {
for (uint32 i = 0; i < _frames.size(); i++) {
_frames[i].surface.free();
}
_frames.clear();
}
GraphicFrame *GraphicResource::getFrame(uint32 frame) {
if (frame >= _frames.size())
error("[GraphicResource::getFrame] Invalid frame index (was: %d, max:%d)", frame, _frames.size() - 1);
return &_frames[frame];
}
void GraphicResource::init(byte *data, int32 size) {
byte *dataPtr = data;
// Read tag
for (uint i = 0; i < sizeof(_data.tag); i++) {
_data.tag[i] = *dataPtr;
++dataPtr;
}
_data.flags = READ_LE_UINT32(dataPtr);
dataPtr += 4;
int32 contentOffset = (int32)READ_LE_UINT32(dataPtr);
dataPtr += 4;
_data.field_C = READ_LE_UINT32(dataPtr);
dataPtr += 4;
_data.field_10 = READ_LE_UINT32(dataPtr);
dataPtr += 4;
_data.field_14 = READ_LE_UINT32(dataPtr);
dataPtr += 4;
uint16 frameCount = READ_LE_UINT16(dataPtr);
dataPtr += 2;
_data.maxWidth = READ_LE_UINT16(dataPtr);
dataPtr += 2;
_frames.resize(frameCount);
// Read frame offsets
int32 prevOffset = (int32)READ_LE_UINT32(dataPtr) + contentOffset;
dataPtr += 4;
int32 nextOffset = 0;
for (int32 i = 0; i < frameCount; i++) {
GraphicFrame frame;
frame.offset = prevOffset;
// Read the offset of the next entry to determine the size of this one
nextOffset = (i < frameCount - 1) ? (int32)READ_LE_UINT32(dataPtr) + contentOffset : size;
dataPtr += 4; // offset
frame.size = (nextOffset > 0) ? nextOffset - prevOffset : size - prevOffset;
_frames[i] = frame;
prevOffset = nextOffset;
}
// Reset pointer
dataPtr = data;
// Read frame data
for (uint32 i = 0; i < frameCount; i++) {
dataPtr = data + _frames[i].offset;
dataPtr += 4; // size
dataPtr += 4; // flag
_frames[i].x = (int16)READ_LE_UINT16(dataPtr);
dataPtr += 2;
_frames[i].y = (int16)READ_LE_UINT16(dataPtr);
dataPtr += 2;
uint16 height = READ_LE_UINT16(dataPtr);
dataPtr += 2;
uint16 width = READ_LE_UINT16(dataPtr);
dataPtr += 2;
if (width > 0 && height > 0) {
_frames[i].surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
_frames[i].surface.copyRectToSurface(dataPtr, width, 0, 0, width, height);
}
}
}
//////////////////////////////////////////////////////////////////////////
// Helper functions
//////////////////////////////////////////////////////////////////////////
uint32 GraphicResource::getFrameCount(AsylumEngine *engine, ResourceId id) {
GraphicResource *resource = new GraphicResource(engine, id);
uint32 frameCount = resource->count();
delete resource;
return frameCount;
}
Common::Rect GraphicResource::getFrameRect(AsylumEngine *engine, ResourceId id, uint32 index) {
GraphicResource *resource = new GraphicResource(engine, id);
GraphicFrame *frame = resource->getFrame(index);
Common::Rect rect = frame->getRect();
delete resource;
return rect;
}
} // end of namespace Asylum