[Scummvm-cvs-logs] SF.net SVN: scummvm:[39452] scummvm/trunk/engines/cine

buddha_ at users.sourceforge.net buddha_ at users.sourceforge.net
Mon Mar 16 21:24:28 CET 2009


Revision: 39452
          http://scummvm.svn.sourceforge.net/scummvm/?rev=39452&view=rev
Author:   buddha_
Date:     2009-03-16 20:24:28 +0000 (Mon, 16 Mar 2009)

Log Message:
-----------
Add endianness handling to Cine::Palette's load and save functions.

Modified Paths:
--------------
    scummvm/trunk/engines/cine/pal.cpp
    scummvm/trunk/engines/cine/pal.h

Modified: scummvm/trunk/engines/cine/pal.cpp
===================================================================
--- scummvm/trunk/engines/cine/pal.cpp	2009-03-16 19:19:59 UTC (rev 39451)
+++ scummvm/trunk/engines/cine/pal.cpp	2009-03-16 20:24:28 UTC (rev 39452)
@@ -161,6 +161,7 @@
 	}
 }
 
+/*! \brief Shift byte to the left by given amount (Handles negative shifting amounts too, otherwise this would be trivial). */
 byte shiftByteLeft(const byte value, const signed shiftLeft) {
 	if (shiftLeft >= 0)
 		return value << shiftLeft;
@@ -168,6 +169,33 @@
 		return value >> abs(shiftLeft);
 }
 
+/*! \brief Is given endian type big endian? (Handles native endian type too, otherwise this would be trivial). */
+bool isBigEndian(const EndianType endianType) {
+	assert(endianType == NATIVE_ENDIAN || endianType == LITTLE_ENDIAN || endianType == BIG_ENDIAN);
+
+	// Handle explicit little and big endian types here
+	if (endianType != NATIVE_ENDIAN) {
+		return (endianType == BIG_ENDIAN);
+	}
+
+	// Handle native endian type here
+#if defined(SCUMM_BIG_ENDIAN)
+	return true;
+#elif defined(SCUMM_LITTLE_ENDIAN)
+	return false;
+#else
+	#error No endianness defined
+#endif
+}
+
+/*! \brief Calculate byte position of given bit position in a multibyte variable using defined endianness. */
+int bytePos(const int bitPos, const int numBytes, const bool bigEndian) {
+	if (bigEndian)
+		return (numBytes - 1) - (bitPos / 8);
+	else // little endian
+		return bitPos / 8;
+}
+
 // a.k.a. palRotate
 Palette &Palette::rotateRight(byte firstIndex, byte lastIndex) {
 	const Color lastColor = _colors[lastIndex];
@@ -183,6 +211,10 @@
 	return _colors.size();
 }
 
+const EndianType Palette::endianType() const {
+	return (_bigEndian ? BIG_ENDIAN : LITTLE_ENDIAN);
+}
+
 Graphics::PixelFormat Palette::colorFormat() const {
 	return _format;
 }
@@ -199,6 +231,10 @@
 	_bMax = (1 << _bBits) - 1;
 }
 
+void Palette::setEndianType(const EndianType endianType) {
+	_bigEndian = isBigEndian(endianType);
+}
+
 // a.k.a. transformPaletteRange
 Palette &Palette::saturatedAddColor(byte firstIndex, byte lastIndex, signed r, signed g, signed b) {
 	assert(firstIndex < colorCount() && lastIndex < colorCount());
@@ -219,37 +255,42 @@
 	_colors[index].b = CLIP<int>(_colors[index].b + b, 0, _bMax);
 }
 
-Palette &Palette::load(const byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors) {
+Palette &Palette::load(const byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors, const EndianType endianType) {
 	assert(format.bytesPerPixel * numColors <= size); // Make sure there's enough input space
 	assert(format.aLoss == 8); // No alpha
 	assert(format.rShift / 8 == (format.rShift + MAX<int>(0, 8 - format.rLoss - 1)) / 8); // R must be inside one byte
 	assert(format.gShift / 8 == (format.gShift + MAX<int>(0, 8 - format.gLoss - 1)) / 8); // G must be inside one byte
 	assert(format.bShift / 8 == (format.bShift + MAX<int>(0, 8 - format.bLoss - 1)) / 8); // B must be inside one byte
 
+	setEndianType(endianType);
 	setColorFormat(format);
 
 	_colors.clear();
 	_colors.resize(numColors);
+
+	const int rBytePos = bytePos(format.rShift, format.bytesPerPixel, isBigEndian(endianType));
+	const int gBytePos = bytePos(format.gShift, format.bytesPerPixel, isBigEndian(endianType));
+	const int bBytePos = bytePos(format.bShift, format.bytesPerPixel, isBigEndian(endianType));
 	
 	for (uint i = 0; i < numColors; i++) {
 		// _rMax, _gMax, _bMax are also used as masks here
-		_colors[i].r = (buf[i * format.bytesPerPixel + (format.rShift / 8)] >> (format.rShift % 8)) & _rMax;
-		_colors[i].g = (buf[i * format.bytesPerPixel + (format.gShift / 8)] >> (format.gShift % 8)) & _gMax;
-		_colors[i].b = (buf[i * format.bytesPerPixel + (format.bShift / 8)] >> (format.bShift % 8)) & _bMax;
+		_colors[i].r = (buf[i * format.bytesPerPixel + rBytePos] >> (format.rShift % 8)) & _rMax;
+		_colors[i].g = (buf[i * format.bytesPerPixel + gBytePos] >> (format.gShift % 8)) & _gMax;
+		_colors[i].b = (buf[i * format.bytesPerPixel + bBytePos] >> (format.bShift % 8)) & _bMax;
 	}
 
 	return *this;
 }
 
-byte *Palette::save(byte *buf, const uint size) const {
-	return save(buf, size, colorFormat(), colorCount());
+byte *Palette::save(byte *buf, const uint size, const EndianType endianType) const {
+	return save(buf, size, colorFormat(), colorCount(), endianType);
 }
 
-byte *Palette::save(byte *buf, const uint size, const Graphics::PixelFormat format) const {
-	return save(buf, size, format, colorCount());
+byte *Palette::save(byte *buf, const uint size, const Graphics::PixelFormat format, const EndianType endianType) const {
+	return save(buf, size, format, colorCount(), endianType);
 }
 
-byte *Palette::save(byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors, const byte firstIndex) const {
+byte *Palette::save(byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors, const EndianType endianType, const byte firstIndex) const {
 	assert(format.bytesPerPixel * numColors <= size); // Make sure there's enough output space
 	assert(format.aLoss == 8); // No alpha
 	assert(format.rShift / 8 == (format.rShift + MAX<int>(0, 8 - format.rLoss - 1)) / 8); // R must be inside one byte
@@ -269,12 +310,16 @@
 	const byte gMask = ((1 << (8 - format.gLoss)) - 1) << (format.gShift % 8);
 	const byte bMask = ((1 << (8 - format.bLoss)) - 1) << (format.bShift % 8);
 
+	const int rBytePos = bytePos(format.rShift, format.bytesPerPixel, isBigEndian(endianType));
+	const int gBytePos = bytePos(format.gShift, format.bytesPerPixel, isBigEndian(endianType));
+	const int bBytePos = bytePos(format.bShift, format.bytesPerPixel, isBigEndian(endianType));
+
 	// Save the palette to the output in the specified format
 	for (uint i = firstIndex; i < firstIndex + numColors; i++) {
 		// _rMax, _gMax, _bMax are also used as masks here
-		buf[i * format.bytesPerPixel + (format.rShift / 8)] |= (shiftByteLeft(_colors[i].r, rShiftLeft) & rMask);
-		buf[i * format.bytesPerPixel + (format.gShift / 8)] |= (shiftByteLeft(_colors[i].g, gShiftLeft) & gMask);
-		buf[i * format.bytesPerPixel + (format.bShift / 8)] |= (shiftByteLeft(_colors[i].b, bShiftLeft) & bMask);
+		buf[i * format.bytesPerPixel + rBytePos] |= (shiftByteLeft(_colors[i].r, rShiftLeft) & rMask);
+		buf[i * format.bytesPerPixel + gBytePos] |= (shiftByteLeft(_colors[i].g, gShiftLeft) & gMask);
+		buf[i * format.bytesPerPixel + bBytePos] |= (shiftByteLeft(_colors[i].b, bShiftLeft) & bMask);
 	}
 
 	// Return the pointer to the output palette

Modified: scummvm/trunk/engines/cine/pal.h
===================================================================
--- scummvm/trunk/engines/cine/pal.h	2009-03-16 19:19:59 UTC (rev 39451)
+++ scummvm/trunk/engines/cine/pal.h	2009-03-16 20:24:28 UTC (rev 39452)
@@ -39,6 +39,15 @@
 /*! \brief The color format used by OSystem's setPalette-function. */
 static const Graphics::PixelFormat kSystemPalFormat = {4, 0, 0, 0, 8, 0, 8, 16, 0};
 
+/*! \brief Endian types. Used at least by Palette class's load and save functions.
+ * TODO: Move somewhere more general as this is definitely not Cine-engine specific
+ */
+enum EndianType {
+	NATIVE_ENDIAN,
+	LITTLE_ENDIAN,
+	BIG_ENDIAN
+};
+
 struct PalEntry {
 	char name[10];
 	byte pal1[16];
@@ -63,45 +72,55 @@
 // TODO: Test
 class Palette {
 public:
-	/*! \brief Load palette from buffer with given color format and number of colors.
+	/*! \brief Load palette from buffer with given color format, endianness and number of colors.
 	 * \param buf Input buffer
 	 * \param size Input buffer size in bytes
 	 * \param format Input color format
 	 * \param numColors Number of colors to load
+	 * \param endianType The endianness of the colors in the input buffer
 	 */
-	Palette &load(const byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors);
+	Palette &load(const byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors, const EndianType endianType);
 
-	/*! \brief Save the whole palette to buffer in original color format.
+	/*! \brief Save the whole palette to buffer in original color format using defined endianness.
 	 * \param buf Output buffer
 	 * \param size Output buffer size in bytes
+	 * \param endianType The endian type to use
 	 */
-	byte *save(byte *buf, const uint size) const;
+	byte *save(byte *buf, const uint size, const EndianType endianType) const;
 
-	/*! \brief Save the whole palette to buffer with given color format.
+	/*! \brief Save the whole palette to buffer in given color format using defined endianness.
 	 * \param buf Output buffer
 	 * \param size Output buffer size in bytes
 	 * \param format Output color format
+	 * \param endianType The endian type to use
 	 */
-	byte *save(byte *buf, const uint size, const Graphics::PixelFormat format) const;
+	byte *save(byte *buf, const uint size, const Graphics::PixelFormat format, const EndianType endianType) const;
 
-	/*! \brief Save (partial) palette to buffer with given color format.
+	/*! \brief Save (partial) palette to buffer in given color format using defined endianness.
 	 * \param buf Output buffer
 	 * \param size Output buffer size in bytes
 	 * \param format Output color format
 	 * \param numColors Number of colors to save
+	 * \param endianType The endian type to use
 	 * \param firstIndex Starting color index (from which onwards to save the colors)
 	 */
-	byte *save(byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors, const byte firstIndex = 0) const;
+	byte *save(byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors, const EndianType endianType, const byte firstIndex = 0) const;
 
 	Palette &rotateRight(byte firstIndex, byte lastIndex);
 	Palette &saturatedAddColor(byte firstIndex, byte lastIndex, signed r, signed g, signed b);	
 	uint colorCount() const;
 
+	/*! \brief The original endian type in which this palette was loaded.
+	 * \note This will always return either BIG_ENDIAN or LITTLE_ENDIAN (So no NATIVE_ENDIAN).
+	 */
+	const EndianType endianType() const;
+
 	/*! \brief The original color format in which this palette was loaded. */
 	Graphics::PixelFormat colorFormat() const;
 
 private:
 	void setColorFormat(const Graphics::PixelFormat format);
+	void setEndianType(const EndianType endianType);
 	void saturatedAddColor(byte index, signed r, signed g, signed b);
 
 private:
@@ -109,9 +128,11 @@
 		uint8 r, g, b;
 	};
 
+	// The used source format, its endianness etc.
 	Graphics::PixelFormat _format;
 	uint _rBits, _gBits, _bBits;
 	uint _rMax, _gMax, _bMax;
+	bool _bigEndian;
 
 	Common::Array<Color> _colors;
 };


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list