Initial commit
This commit is contained in:
270
engines/hadesch/pod_image.cpp
Normal file
270
engines/hadesch/pod_image.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/* 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/>.
|
||||
*
|
||||
* Copyright 2020 Google
|
||||
*
|
||||
*/
|
||||
#include "common/debug.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "hadesch/pod_image.h"
|
||||
#include "hadesch/tag_file.h"
|
||||
#include "hadesch/baptr.h"
|
||||
#include "hadesch/gfx_context.h"
|
||||
|
||||
namespace Hadesch {
|
||||
PodImage::PodImage() {
|
||||
_w = 0;
|
||||
_h = 0;
|
||||
_pos = Common::Point(0, 0);
|
||||
_ncolors = 0;
|
||||
}
|
||||
|
||||
PodImage::~PodImage() {
|
||||
}
|
||||
|
||||
bool PodImage::loadImage(const PodFile &col, int index) {
|
||||
char bufname[256];
|
||||
snprintf (bufname, sizeof(bufname) - 1, "%d", index);
|
||||
Common::SharedPtr<Common::SeekableReadStream> dataStream(col.getFileStream(bufname));
|
||||
if (!dataStream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::SharedPtr<Common::SeekableReadStream> palStream(col.getFileStream("0"));
|
||||
TagFile palTags;
|
||||
if (!palStream || !palTags.openStoreCel(palStream)) {
|
||||
debug("Couldn't open palette");
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::SharedPtr<Common::SeekableReadStream> palTagStream(palTags.getFileStream(MKTAG('P', 'A', 'L', ' ')));
|
||||
|
||||
if (!palTagStream) {
|
||||
debug("Couldn't open PAL palette in image %s", col.getDebugName().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
uint palSize = palTagStream->size();
|
||||
if (palSize > 256 * 4) {
|
||||
debug("Palette unexpectedly large");
|
||||
palSize = 256 * 4;
|
||||
}
|
||||
|
||||
_palette = sharedPtrByteAlloc(256 * 4);
|
||||
memset(_palette.get(), 0, 256 * 4);
|
||||
_paletteCursor = sharedPtrByteAlloc(256 * 3);
|
||||
memset(_paletteCursor.get(), 0, 256 * 3);
|
||||
|
||||
palTagStream->read(_palette.get(), palSize);
|
||||
_ncolors = palSize / 4;
|
||||
|
||||
for (int i = 0; i < _ncolors; i++) {
|
||||
int color = _palette.get()[4 * i] & 0xff;
|
||||
|
||||
_paletteCursor.get()[3 * color ] = _palette.get()[4 * i + 1];
|
||||
_paletteCursor.get()[3 * color + 1] = _palette.get()[4 * i + 2];
|
||||
_paletteCursor.get()[3 * color + 2] = _palette.get()[4 * i + 3];
|
||||
}
|
||||
|
||||
TagFile dataTags;
|
||||
if (!dataTags.openStoreCel(dataStream)) {
|
||||
debug("Couldn't open data for image %d", index);
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::ScopedPtr<Common::SeekableReadStream> infoTagStream(dataTags.getFileStream(MKTAG('I', 'N', 'F', 'O')));
|
||||
|
||||
if (!infoTagStream) {
|
||||
debug("Couldn't open INFO");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (infoTagStream->size() < 0x1c) {
|
||||
debug("INFO section too small");
|
||||
return false;
|
||||
}
|
||||
|
||||
infoTagStream->skip(0xc);
|
||||
int x = -(int32)infoTagStream->readUint32BE();
|
||||
int y = -(int32)infoTagStream->readUint32BE();
|
||||
_pos = Common::Point(x,y);
|
||||
_w = infoTagStream->readUint32BE();
|
||||
_h = infoTagStream->readUint32BE();
|
||||
|
||||
// Empty image
|
||||
if (_w < 0 || _h < 0) {
|
||||
_w = 0;
|
||||
_h = 0;
|
||||
_pixels = sharedPtrByteAlloc(1);
|
||||
memset(_pixels.get(), 0, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
_pixels = sharedPtrByteAlloc(_w * _h);
|
||||
memset(_pixels.get(), 0, _w * _h);
|
||||
// TODO: check this
|
||||
_hotspot = Common::Point(_w / 2, _h / 2);
|
||||
|
||||
Common::ScopedPtr<Common::SeekableReadStream> dataTagStream(dataTags.getFileStream(MKTAG('D', 'A', 'T', 'A')));
|
||||
|
||||
if (!dataTagStream) {
|
||||
debug("Couldn't open DATA in image %s, index %d", col.getDebugName().c_str(), index);
|
||||
return false;
|
||||
}
|
||||
|
||||
int linerem = _w;
|
||||
int line = 0;
|
||||
|
||||
for (int pos = 0; pos < _w * _h && !dataTagStream->eos(); ) {
|
||||
byte rlelen = dataTagStream->readByte();
|
||||
byte rleval = dataTagStream->readByte();
|
||||
if (dataTagStream->eos()) {
|
||||
break;
|
||||
}
|
||||
if (rlelen != 0) {
|
||||
int len = rlelen;
|
||||
if (len > linerem) {
|
||||
len = linerem;
|
||||
}
|
||||
memset(_pixels.get() + pos, rleval, len);
|
||||
linerem -= len;
|
||||
pos += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rleval != 0) {
|
||||
int len = rleval;
|
||||
if (len > linerem) {
|
||||
len = linerem;
|
||||
}
|
||||
dataTagStream->read(_pixels.get() + pos, len);
|
||||
linerem -= len;
|
||||
pos += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
// End of line
|
||||
line++;
|
||||
linerem = _w;
|
||||
pos = line * _w;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Naive implementation as it's used very rarely
|
||||
// Nearest neighbour, unoptimized
|
||||
void PodImage::makeScale(int scale) const {
|
||||
struct ScaledVersion sv;
|
||||
sv._w = _w * scale / 100;
|
||||
sv._h = _h * scale / 100;
|
||||
sv._pixels = sharedPtrByteAlloc(sv._h * sv._w);
|
||||
for (int x = 0; x < sv._w; x++) {
|
||||
int ox = x * _w / sv._w;
|
||||
if (ox >= _w)
|
||||
ox = _w - 1;
|
||||
if (ox < 0)
|
||||
ox = 0;
|
||||
for (int y = 0; y < sv._h; y++) {
|
||||
int oy = y * _h / sv._h;
|
||||
if (oy >= _h)
|
||||
oy = _h - 1;
|
||||
if (oy < 0)
|
||||
oy = 0;
|
||||
sv._pixels.get()[x + y * sv._w] = _pixels.get()[ox + oy * _w];
|
||||
}
|
||||
}
|
||||
_scales[scale] = sv;
|
||||
}
|
||||
|
||||
void PodImage::render(Common::SharedPtr<GfxContext> context,
|
||||
Common::Point offset,
|
||||
int colourScale,
|
||||
int scale) const {
|
||||
byte *originalPalette = _palette.get();
|
||||
byte *scaledPalette = nullptr;
|
||||
if (colourScale != 0x100) {
|
||||
scaledPalette = new byte[_ncolors * 4];
|
||||
for (unsigned i = 0; (int)i < _ncolors; i++) {
|
||||
scaledPalette[4 * i] = originalPalette[4 * i];
|
||||
scaledPalette[4 * i + 1] = (originalPalette[4 * i + 1] * colourScale) >> 8;
|
||||
scaledPalette[4 * i + 2] = (originalPalette[4 * i + 2] * colourScale) >> 8;
|
||||
scaledPalette[4 * i + 3] = (originalPalette[4 * i + 3] * colourScale) >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (scale == 100)
|
||||
context->blitPodImage(_pixels.get(), _w, _w, _h,
|
||||
scaledPalette ? scaledPalette : originalPalette, _ncolors, _pos + offset);
|
||||
else {
|
||||
if (!_scales.contains(scale))
|
||||
makeScale(scale);
|
||||
context->blitPodImage(_scales[scale]._pixels.get(), _scales[scale]._w, _scales[scale]._w, _scales[scale]._h,
|
||||
scaledPalette ? scaledPalette : originalPalette, _ncolors, _pos * (scale / 100.0) + offset);
|
||||
}
|
||||
if (scaledPalette)
|
||||
delete [] scaledPalette;
|
||||
}
|
||||
|
||||
Common::Point PodImage::getOffset() const {
|
||||
return _pos;
|
||||
}
|
||||
|
||||
uint16 PodImage::getWidth() const {
|
||||
return _w;
|
||||
}
|
||||
|
||||
uint16 PodImage::getHeight() const {
|
||||
return _h;
|
||||
}
|
||||
|
||||
uint16 PodImage::getHotspotX() const {
|
||||
return _hotspot.x;
|
||||
}
|
||||
|
||||
uint16 PodImage::getHotspotY() const {
|
||||
return _hotspot.y;
|
||||
}
|
||||
|
||||
byte PodImage::getKeyColor() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const byte *PodImage::getSurface() const {
|
||||
return _pixels.get();
|
||||
}
|
||||
|
||||
const byte *PodImage::getPalette() const {
|
||||
return _paletteCursor.get();
|
||||
}
|
||||
|
||||
byte PodImage::getPaletteStartIndex() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 PodImage::getPaletteCount() const {
|
||||
return 256;
|
||||
}
|
||||
|
||||
void PodImage::setHotspot(Common::Point hotspot) {
|
||||
_hotspot = hotspot;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user