/* 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ /* * This code is based on original Tony Tough source code * * Copyright (c) 1997-2003 Nayma Software */ #include "tony/utils.h" #include "tony/tony.h" #include "tony/mpal/lzo.h" namespace Tony { /** * Extracts a string from a data stream * @param df data stream */ Common::String readString(Common::ReadStream &df) { Common::String var; uint8 len = df.readByte(); for (int i = 0; i < len; i++) { char c; c = df.readByte(); var += c; } return var; } /****************************************************************************\ * RMPoint methods \****************************************************************************/ /** * Constructor */ RMPoint::RMPoint() { _x = _y = 0; } /** * Copy constructor */ RMPoint::RMPoint(const RMPoint &p) { _x = p._x; _y = p._y; } /** * Constructor with integer parameters */ RMPoint::RMPoint(int x1, int y1) { _x = x1; _y = y1; } /** * Copy operator */ RMPoint &RMPoint::operator=(RMPoint p) { _x = p._x; _y = p._y; return *this; } /** * Set a point */ void RMPoint::set(int x1, int y1) { _x = x1; _y = y1; } /** * Offsets the point by another point */ void RMPoint::offset(const RMPoint &p) { _x += p._x; _y += p._y; } /** * Offsets the point by a specified offset */ void RMPoint::offset(int xOff, int yOff) { _x += xOff; _y += yOff; } /** * Sums together two points */ RMPoint operator+(RMPoint p1, RMPoint p2) { RMPoint p(p1); return (p += p2); } /** * Subtracts two points */ RMPoint operator-(RMPoint p1, RMPoint p2) { RMPoint p(p1); return (p -= p2); } /** * Sum (offset) of a point */ RMPoint &RMPoint::operator+=(RMPoint p) { offset(p); return *this; } /** * Subtract (offset) of a point */ RMPoint &RMPoint::operator-=(RMPoint p) { offset(-p); return *this; } /** * Inverts a point */ RMPoint RMPoint::operator-() { RMPoint p; p._x = -_x; p._y = -_y; return p; } /** * Equality operator */ bool RMPoint::operator==(RMPoint p) { return ((_x == p._x) && (_y == p._y)); } /** * Not equal operator */ bool RMPoint::operator!=(RMPoint p) { return ((_x != p._x) || (_y != p._y)); } /** * Reads a point from a stream */ void RMPoint::readFromStream(Common::ReadStream &ds) { _x = ds.readSint32LE(); _y = ds.readSint32LE(); } /****************************************************************************\ * RMPointReference methods \****************************************************************************/ RMPointReference::RMPointReference(int &x, int &y): _x(x), _y(y) { } RMPointReference &RMPointReference::operator=(const RMPoint &p) { _x = p._x; _y = p._y; return *this; } RMPointReference &RMPointReference::operator-=(const RMPoint &p) { _x -= p._x; _y -= p._y; return *this; } RMPointReference::operator RMPoint() const { return RMPoint(_x, _y); } /****************************************************************************\ * RMRect methods \****************************************************************************/ RMRect::RMRect(): _topLeft(_x1, _y1), _bottomRight(_x2, _y2) { setEmpty(); } void RMRect::setEmpty() { _x1 = _y1 = _x2 = _y2 = 0; } RMRect::RMRect(const RMPoint &p1, const RMPoint &p2): _topLeft(_x1, _y1), _bottomRight(_x2, _y2) { setRect(p1, p2); } RMRect::RMRect(int X1, int Y1, int X2, int Y2): _topLeft(_x1, _y1), _bottomRight(_x2, _y2) { setRect(X1, Y1, X2, Y2); } RMRect::RMRect(const RMRect &rc): _topLeft(_x1, _y1), _bottomRight(_x2, _y2) { copyRect(rc); } void RMRect::setRect(const RMPoint &p1, const RMPoint &p2) { _x1 = p1._x; _y1 = p1._y; _x2 = p2._x; _y2 = p2._y; } void RMRect::setRect(int X1, int Y1, int X2, int Y2) { _x1 = X1; _y1 = Y1; _x2 = X2; _y2 = Y2; } void RMRect::setRect(const RMRect &rc) { copyRect(rc); } void RMRect::copyRect(const RMRect &rc) { _x1 = rc._x1; _y1 = rc._y1; _x2 = rc._x2; _y2 = rc._y2; } RMPointReference &RMRect::topLeft() { return _topLeft; } RMPointReference &RMRect::bottomRight() { return _bottomRight; } RMPoint RMRect::center() { return RMPoint((_x2 - _x1) / 2, (_y2 - _y1) / 2); } int RMRect::width() const { return _x2 - _x1; } int RMRect::height() const { return _y2 - _y1; } int RMRect::size() const { return width() * height(); } RMRect::operator Common::Rect() const { return Common::Rect(_x1, _y1, _x2, _y2); } bool RMRect::isEmpty() const { return (_x1 == 0 && _y1 == 0 && _x2 == 0 && _y2 == 0); } const RMRect &RMRect::operator=(const RMRect &rc) { copyRect(rc); return *this; } void RMRect::offset(int xOff, int yOff) { _x1 += xOff; _y1 += yOff; _x2 += xOff; _y2 += yOff; } void RMRect::offset(const RMPoint &p) { _x1 += p._x; _y1 += p._y; _x2 += p._x; _y2 += p._y; } const RMRect &RMRect::operator+=(RMPoint p) { offset(p); return *this; } const RMRect &RMRect::operator-=(RMPoint p) { offset(-p); return *this; } RMRect operator+(const RMRect &rc, RMPoint p) { RMRect r(rc); return (r += p); } RMRect operator-(const RMRect &rc, RMPoint p) { RMRect r(rc); return (r -= p); } RMRect operator+(RMPoint p, const RMRect &rc) { RMRect r(rc); return (r += p); } RMRect operator-(RMPoint p, const RMRect &rc) { RMRect r(rc); return (r += p); } bool RMRect::operator==(const RMRect &rc) { return ((_x1 == rc._x1) && (_y1 == rc._y1) && (_x2 == rc._x2) && (_y2 == rc._y2)); } bool RMRect::operator!=(const RMRect &rc) { return ((_x1 != rc._x1) || (_y1 != rc._y1) || (_x2 != rc._x2) || (_y2 != rc._y2)); } void RMRect::normalizeRect() { setRect(MIN(_x1, _x2), MIN(_y1, _y2), MAX(_x1, _x2), MAX(_y1, _y2)); } void RMRect::readFromStream(Common::ReadStream &ds) { _x1 = ds.readSint32LE(); _y1 = ds.readSint32LE(); _x2 = ds.readSint32LE(); _y2 = ds.readSint32LE(); } /** * Check if RMPoint is in RMRect */ bool RMRect::ptInRect(const RMPoint &pt) { return (pt._x >= _x1 && pt._x <= _x2 && pt._y >= _y1 && pt._y <= _y2); } /****************************************************************************\ * Resource Update \****************************************************************************/ RMResUpdate::RMResUpdate() { _infos = NULL; _numUpd = 0; } RMResUpdate::~RMResUpdate() { if (_infos) { delete[] _infos; _infos = NULL; } if (_hFile.isOpen()) _hFile.close(); } void RMResUpdate::init(const Common::String &fileName) { // Open the resource update file if (!_hFile.open(fileName)) // It doesn't exist, so exit immediately return; _hFile.readByte(); // Version, unused _numUpd = _hFile.readUint32LE(); _infos = new ResUpdInfo[_numUpd]; // Load the index of the resources in the file for (uint32 i = 0; i < _numUpd; ++i) { ResUpdInfo &info = _infos[i]; info._dwRes = _hFile.readUint32LE(); info._offset = _hFile.readUint32LE(); info._size = _hFile.readUint32LE(); info._cmpSize = _hFile.readUint32LE(); } } MpalHandle RMResUpdate::queryResource(uint32 dwRes) { // If there isn't an update file, return NULL if (!_hFile.isOpen()) return NULL; uint32 i; for (i = 0; i < _numUpd; ++i) if (_infos[i]._dwRes == dwRes) // Found the index break; if (i == _numUpd) // Couldn't find a matching resource, so return NULL return NULL; const ResUpdInfo &info = _infos[i]; byte *cmpBuf = new byte[info._cmpSize]; uint32 dwRead; // Move to the correct offset and read in the compressed data _hFile.seek(info._offset); dwRead = _hFile.read(cmpBuf, info._cmpSize); if (info._cmpSize > dwRead) { // Error occurred reading data, so return NULL delete[] cmpBuf; return NULL; } // Allocate space for the output resource MpalHandle destBuf = globalAllocate(0, info._size); byte *lpDestBuf = (byte *)globalLock(destBuf); uint32 dwSize; // Decompress the data lzo1x_decompress(cmpBuf, info._cmpSize, lpDestBuf, &dwSize); // Delete buffer for compressed data delete [] cmpBuf; // Return the resource globalUnlock(destBuf); return destBuf; } } // End of namespace Tony