* Fixed compression code, old code was unreliable and failed at random

(don't use zlib's compress function)
* More refactory work, ready for merge
This commit is contained in:
Antidote 2013-07-21 20:06:54 -07:00
parent d06c96d3aa
commit b7b4df52f3
34 changed files with 408 additions and 318 deletions

View File

@ -20,6 +20,9 @@
#include "Types.hpp"
namespace zelda
{
enum BowType : char
{
BowNone,
@ -105,5 +108,6 @@ enum ALTTPTagAlong
AfterBoss
};
} // zelda
#endif // __DOXYGEN_IGNORE__
#endif // __ALTTP_ENUMS_HPP__

View File

@ -24,9 +24,9 @@
namespace zelda
{
class ALTTPFile;
namespace io
{
/*! \class ALTTPFileReader
* \brief A Link to the Past save data reader class
*
@ -34,10 +34,10 @@ namespace io
* all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader
*/
class ALTTPFileReader : public io::BinaryReader
class ALTTPFileReader : protected BinaryReader
{
BINARYREADER_BASE
public:
/*! \brief This constructor takes an existing buffer to read from.
*

View File

@ -34,7 +34,7 @@ namespace io
* all work is done using a memory buffer, and not written directly to the disk.
* \sa BinaryReader
*/
class ALTTPFileWriter : public io::BinaryWriter
class ALTTPFileWriter : protected BinaryWriter
{
BINARYWRITER_BASE

View File

@ -23,6 +23,7 @@ namespace zelda
{
namespace io
{
/*! \class BinaryReader
* \brief A Stream class for reading binary data
*
@ -177,4 +178,5 @@ protected:
private: \
typedef zelda::io::BinaryReader base;
#endif // BINARYREADER_BASE
#endif // __BINARYREADER_HPP__

View File

@ -138,6 +138,13 @@ public:
* \param str The string to write to the buffer
*/
void writeUnicode(const std::string& str);
/*! \brief Writes an string to the buffer and advances the buffer.
*
* \sa Endian
* \param str The string to write to the buffer
*/
void writeString(const std::string& str);
protected:
Int8 readByte();
Int8* readBytes(Int64);

View File

@ -25,7 +25,7 @@ namespace io
namespace Compression
{
Int32 decompressZlib(Uint8* src, Uint32 srcLen, Uint8* dst, Uint32 dstLen);
void compressZlib(const Uint8* src, Uint32 srcLen, Uint8* dst, Uint32* dstLen);
Int32 compressZlib(const Uint8* src, Uint32 srcLen, Uint8* dst, Uint32 dstLen);
}
}
}

View File

@ -34,7 +34,7 @@ namespace io
* all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader
*/
class MCFileReader : public io::BinaryReader
class MCFileReader : protected BinaryReader
{
BINARYREADER_BASE
public:

View File

@ -24,6 +24,9 @@ namespace zelda
class MCFile;
namespace io
{
/*! \class MCFileWriter
* \brief The Minish Cap Save save data writer class
*
@ -31,7 +34,7 @@ class MCFile;
* all work is done using a memory buffer, and not written directly from the disk.
* \sa BinaryWriter
*/
class MCFileWriter : public io::BinaryWriter
class MCFileWriter : protected BinaryWriter
{
BINARYWRITER_BASE
public:
@ -64,6 +67,7 @@ private:
void unscramble();
};
} // io
} // zelda
#endif // __MCFILEWRITER_HPP__

View File

@ -80,16 +80,16 @@ public:
* \throw IOException
*/
virtual void writeBit(bool val);
/*! \brief Writes a byte at the current position and advances the position by one byte.
* \param byte The value to write
* \throw IOException
*/
virtual void writeUByte(Uint8 byte);
/*! \brief Writes a byte at the current position and advances the position by one byte.
* \param byte The value to write
* \throw IOException
*/
* \param byte The value to write
* \throw IOException
*/
virtual void writeByte(Int8 byte);
/*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length

View File

@ -17,6 +17,9 @@
#include <limits.h>
#ifdef __cplusplus
namespace zelda
{
/*! \enum Endian
* \brief Allows the user to specify the Endianness of data.<br />
* The proper actions are automatically taken depending on platform and
@ -27,6 +30,8 @@ enum Endian
LittleEndian, //!< Specifies that the Stream is Little Endian (LSB)
BigEndian //!< Specifies that the Stream is Big Endian (MSB)
};
} // zelda
#endif
// 8 bits integer types
#if UCHAR_MAX == 0xFF

View File

@ -12,12 +12,13 @@
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#ifndef __WII_SAVE_READER_HPP__
#define __WII_SAVE_READER_HPP__
#include <Types.hpp>
#include <utility.hpp>
#include <BinaryReader.hpp>
#include "Types.hpp"
#include "utility.hpp"
#include "BinaryReader.hpp"
namespace zelda
{
@ -36,7 +37,7 @@ namespace io
* all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader
*/
class WiiSaveReader : public io::BinaryReader
class WiiSaveReader : protected BinaryReader
{
BINARYREADER_BASE
public:

View File

@ -22,7 +22,6 @@
namespace zelda
{
class WiiSave;
class WiiBanner;
class WiiFile;
@ -38,7 +37,7 @@ namespace io
* all work is done using a memory buffer, and not written directly to the disk.
* \sa BinaryReader
*/
class WiiSaveWriter : public io::BinaryWriter
class WiiSaveWriter : protected BinaryWriter
{
BINARYWRITER_BASE
public:

View File

@ -16,7 +16,7 @@
#ifndef ZQUEST_HPP
#define ZQUEST_HPP
#include <Types.hpp>
#include "Types.hpp"
#include <string>
#include <vector>
@ -25,65 +25,70 @@ namespace zelda
/*!
* \brief The ZQuest class
*/
class ZQuest
class ZQuestFile
{
public:
/*!
* \brief Major
* \brief The current major version of the ZQuest format
*/
static const Uint32 Major;
/*!
* \brief Minor
* \brief The current minor version of the ZQuest format
*/
static const Uint32 Minor;
/*!
* \brief Revision
* \brief The current revision of the ZQuest format
*/
static const Uint32 Revision;
/*!
* \brief Build
* \brief The current build of the ZQuest format
*/
static const Uint32 Build;
/*!
* \brief Version
* \brief The current version of the ZQuest format
*/
static const Uint32 Version;
/*!
* \brief Magic
* \brief The magic number used to identify the file e.g. "ZQS1"
*/
static const Uint32 Magic;
/*!
* \brief The Game enum
* \enum Game
* \brief The list of games currently supported by ZQuest
*/
enum Game
{
NoGame,
LegendofZelda,
AdventureOfLink,
ALinkToThePast,
LinksAwakening,
OcarinaOfTime,
OcarinaOfTime3D,
MajorasMask,
OracleOfSeasons,
OracleOfAges,
FourSwords,
WindWaker,
FourSwordsAdventures,
MinishCap,
TwilightPrincess,
PhantomHourglass,
SpiritTracks,
SkywardSword,
ALinkBetweenWorlds // Not released
NoGame, //!< None or Unsupported
LoZ, //!< Legend of Zelda
AoL, //!< Adventure of Link
ALttP, //!< A Link to the Past
LA, //!< Links Awakening
OoT, //!< Ocarin of Time
OoT3D, //!< Ocarina of Time 3D
MM, //!< Majora's Mask
OoS, //!< Oracle of Season
OoA, //!< Oracle of Ages
FS, //!< Four Swords
WW, //!< Wind Waker
FSA, //!< Four Swords Adventures
MC, //!< Minish Cap
TP, //!< Twilight Princess
PH, //!< Phantom Hourglass
ST, //!< Spirit Tracks
SS, //!< Skyward Sword
ALBW, //!< A Link Between Worlds
// Add more games here
// This must always be last
GameCount //!< Total number of supported games
};
/*!
* \brief ZQuest
*/
ZQuest();
ZQuestFile();
/*!
* \brief ZQuest
@ -92,8 +97,8 @@ public:
* \param data
* \param length
*/
ZQuest(Game game, Endian endian, Uint8* data, Uint32 length);
~ZQuest();
ZQuestFile(Game game, Endian endian, Uint8* data, Uint32 length);
~ZQuestFile();
/*!
* \brief setGame
@ -121,9 +126,10 @@ public:
/*!
* \brief setData
* \param data
* \param data The data to assign
* \param length The length of the data
*/
void setData(Uint8* data);
void setData(Uint8* data, Uint32 length);
/*!
* \brief data
@ -131,12 +137,6 @@ public:
*/
Uint8* data() const;
/*!
* \brief setLength
* \param length
*/
void setLength(Uint32 length);
/*!
* \brief length
* \return

View File

@ -20,16 +20,18 @@
namespace zelda
{
class ZQuest;
class ZQuestFile;
namespace io
{
/*!
* \brief The ZQuestFileReader class
*/
class ZQuestFileReader : public io::BinaryReader
class ZQuestFileReader : protected BinaryReader
{
BINARYREADER_BASE
public:
/*!
* \brief ZQuestFileReader
@ -48,7 +50,7 @@ public:
* \brief read
* \return
*/
ZQuest* read();
ZQuestFile* read();
};
} // io

View File

@ -20,7 +20,7 @@
namespace zelda
{
class ZQuest;
class ZQuestFile;
namespace io
{
@ -28,7 +28,7 @@ namespace io
/*!
* \brief The ZQuestFileWriter class
*/
class ZQuestFileWriter : public io::BinaryWriter
class ZQuestFileWriter : protected BinaryWriter
{
BINARYWRITER_BASE
@ -51,7 +51,7 @@ public:
* \param quest
* \param compress
*/
void write(ZQuest* quest, bool compress = true);
void write(ZQuestFile* quest, bool compress = true);
};
} // io

View File

@ -88,7 +88,7 @@ extern "C"
* Typedefs:
*/
typedef struct
typedef struct auth_md5Ctx_
{
unsigned int len;
unsigned int ABCD[4];

View File

@ -19,13 +19,19 @@
#include <string>
#include "Types.hpp"
bool isEmpty(Int8*, size_t);
namespace zelda
{
namespace utility
{
unsigned short swapU16(unsigned short val );
short swap16 (short val );
unsigned int swapU32(unsigned int val);
int swap32 (int val );
long long swap64 (long long val);
bool isEmpty(Int8*, Uint32);
Uint16 swapU16(Uint16 val );
Int16 swap16 (Int16 val );
Uint32 swapU32(Uint32 val);
Int32 swap32 (Int32 val );
Uint64 swapU64(Uint64 val);
Int64 swap64 (Int64 val);
float swapFloat(float val);
double swapDouble(double val);
@ -36,4 +42,8 @@ void fillRandom(Uint8 * rndArea, Uint8 count);
void yaz0Decode(Uint8* src, Uint8* dst, Uint32 uncompressedSize);
} // utility
} // zelda
#endif

View File

@ -50,9 +50,9 @@ HEADERS += \
include/MCFileWriter.hpp \
include/ZQuestFileWriter.hpp \
include/ZQuestFileReader.hpp \
include/ZQuest.hpp \
include/Compression.hpp \
include/WiiImage.hpp
include/WiiImage.hpp \
include/ZQuestFile.hpp
SOURCES += \
src/utility.cpp \
@ -79,9 +79,9 @@ SOURCES += \
src/MCFileWriter.cpp \
src/ZQuestFileWriter.cpp \
src/ZQuestFileReader.cpp \
src/ZQuest.cpp \
src/Compression.cpp \
src/WiiImage.cpp
src/WiiImage.cpp \
src/ZQuestFile.cpp
system("exec doxygen libzelda.conf")
#system("cd doc/latex && make")

View File

@ -103,8 +103,8 @@ Int16 BinaryReader::readInt16()
Int16 ret = *(Int16*)(m_data + m_position);
m_position += 2;
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
ret = swap16(ret);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swap16(ret);
return ret;
}
@ -120,8 +120,8 @@ Uint16 BinaryReader::readUInt16()
Uint16 ret = *(Uint16*)(m_data + m_position);
m_position += 2;
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
ret = swapU16(ret);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swapU16(ret);
return ret;
}
@ -138,8 +138,8 @@ Int32 BinaryReader::readInt32()
Int32 ret = *(Int32*)(m_data + m_position);
m_position += 4;
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
ret = swap32(ret);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swap32(ret);
return ret;
}
@ -156,8 +156,8 @@ Uint32 BinaryReader::readUInt32()
Uint32 ret = *(Uint32*)(m_data + m_position);
m_position += 4;
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
ret = swapU32(ret);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swapU32(ret);
return ret;
}
@ -174,8 +174,8 @@ Int64 BinaryReader::readInt64()
Int64 ret = *(Int64*)(m_data + m_position);
m_position += 8;
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
ret = swap64(ret);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swap64(ret);
return ret;
}
@ -191,8 +191,8 @@ Uint64 BinaryReader::readUInt64()
Uint64 ret = *(Uint64*)(m_data + m_position);
m_position += 8;
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
ret = swap64(ret);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swapU64(ret);
return ret;
}
@ -209,8 +209,8 @@ float BinaryReader::readFloat()
float ret = *(float*)(m_data + m_position);
m_position += 4;
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
ret = swapFloat(ret);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swapFloat(ret);
return ret;
}
@ -227,8 +227,8 @@ double BinaryReader::readDouble()
double ret = *(double*)(m_data + m_position);
m_position += 8;
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
ret = swapDouble(ret);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swapDouble(ret);
return ret;
}

View File

@ -105,8 +105,8 @@ void BinaryWriter::writeInt16(Int16 val)
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteInt16 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
val = swap16(val);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swap16(val);
*(Int16*)(m_data + m_position) = val;
m_position += sizeof(Int16);
@ -126,8 +126,8 @@ void BinaryWriter::writeUInt16(Uint16 val)
throw error::IOException("BinaryWriter::WriteUInt16 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
val = swapU16(val);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swapU16(val);
*(Uint16*)(m_data + m_position) = val;
m_position += sizeof(Uint16);
@ -146,8 +146,8 @@ void BinaryWriter::writeInt32(Int32 val)
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteInt32 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
val = swap32(val);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swap32(val);
*(Int32*)(m_data + m_position) = val;
m_position += sizeof(Int32);
@ -166,8 +166,8 @@ void BinaryWriter::writeUInt32(Uint32 val)
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteUInt32 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
val = swap32(val);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swapU32(val);
*(Uint32*)(m_data + m_position) = val;
m_position += sizeof(Uint32);
@ -187,8 +187,8 @@ void BinaryWriter::writeInt64(Int64 val)
throw error::IOException("BinaryWriter::WriteInt64 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
val = swap64(val);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swap64(val);
*(Int64*)(m_data + m_position) = val;
m_position += sizeof(Int64);
@ -207,8 +207,8 @@ void BinaryWriter::writeUInt64(Uint64 val)
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteUInt64 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
val = swap64(val);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swapU64(val);
*(Uint64*)(m_data + m_position) = val;
m_position += sizeof(Uint64);
@ -227,8 +227,8 @@ void BinaryWriter::writeFloat(float val)
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteFloat -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
val = swapFloat(val);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swapFloat(val);
*(float*)(m_data + m_position) = val;
m_position += sizeof(float);
@ -247,8 +247,8 @@ void BinaryWriter::writeDouble(double val)
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteDouble -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian))
val = swapDouble(val);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swapDouble(val);
*(double*)(m_data + m_position)= val;
m_position += sizeof(double);
@ -287,6 +287,16 @@ void BinaryWriter::writeUnicode(const std::string& str)
}
}
void BinaryWriter::writeString(const std::string& str)
{
for (Uint8 c : str)
{
if (c != '\0')
writeUByte(c);
}
writeUByte(0);
}
bool BinaryWriter::isOpenForReading()
{
return false;

View File

@ -14,6 +14,8 @@
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "Compression.hpp"
#include "Exception.hpp"
#include <iostream>
#include <zlib.h>
@ -26,7 +28,7 @@ namespace Compression
Int32 decompressZlib(Uint8 *src, Uint32 srcLen, Uint8* dst, Uint32 dstLen)
{
z_stream strm;
z_stream strm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
strm.total_in = strm.avail_in = srcLen;
strm.total_out = strm.avail_out = dstLen;
strm.next_in = (Bytef *) src;
@ -39,18 +41,20 @@ Int32 decompressZlib(Uint8 *src, Uint32 srcLen, Uint8* dst, Uint32 dstLen)
Int32 err = -1;
Int32 ret = -1;
err = inflateInit2(&strm, (15 + 32)); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib
if (err == Z_OK) {
err = inflateInit(&strm); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib
if (err == Z_OK)
{
err = inflate(&strm, Z_FINISH);
if (err == Z_STREAM_END) {
if (err == Z_STREAM_END)
ret = strm.total_out;
}
else {
inflateEnd(&strm);
return err;
else
{
inflateEnd(&strm);
return err;
}
}
else {
else
{
inflateEnd(&strm);
return err;
}
@ -60,9 +64,43 @@ Int32 decompressZlib(Uint8 *src, Uint32 srcLen, Uint8* dst, Uint32 dstLen)
return ret;
}
void compressZlib(const Uint8 *src, Uint32 srcLen, Uint8 *dst, Uint32* dstLen)
Int32 compressZlib(const Uint8 *src, Uint32 srcLen, Uint8 *dst, Uint32 dstLen)
{
compress(dst, (uLongf*)dstLen, src, srcLen);
z_stream strm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
strm.total_in = strm.avail_in = srcLen;
strm.total_out = strm.avail_out = dstLen;
strm.next_in = (Bytef *) src;
strm.next_out = (Bytef *) dst;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
Int32 err = -1;
Int32 ret = -1;
err = deflateInit(&strm, Z_BEST_COMPRESSION);
if (err == Z_OK)
{
err = deflate(&strm, Z_FINISH);
if (err == Z_STREAM_END)
ret = strm.total_out;
else
{
deflateEnd(&strm);
return err;
}
}
else
{
deflateEnd(&strm);
return err;
}
deflateEnd(&strm);
return ret;
}
} // Compression

View File

@ -17,6 +17,8 @@
namespace zelda
{
namespace io
{
MCFileWriter::MCFileWriter(Uint8* data, Uint64 length)
: base(data, length)
@ -93,4 +95,5 @@ void MCFileWriter::unscramble()
}
}
} // io
} // zelda

View File

@ -156,9 +156,9 @@ std::vector<std::string> TextStream::readLines(Uint32 numLines)
std::string TextStream::readLineAt(Uint32 line)
{
if (m_accessmode != ReadOnly && m_accessmode != ReadWrite)
throw error::InvalidOperationException("Stream not open for reading");
throw error::InvalidOperationException("TextStream::readLineAt -> Stream not open for reading");
if (line <= 0)
throw error::InvalidOperationException("A line cannot be zero indexed");
throw error::InvalidOperationException("TextStream::readLineAt -> A line cannot be zero indexed");
if ((line - 1) >= m_lines.size())
throw error::IOException("TextStream::readLineAt -> Line index out of range");

View File

@ -72,7 +72,7 @@ Uint8 *WiiImage::toRGBA()
Uint16 oldpixel = *(Uint16*)(m_data + ((iv++) * 2));
//if((x >= m_width) || (y >= m_height))
// continue;
oldpixel = swapU16(oldpixel);
oldpixel = utility::swapU16(oldpixel);
if(oldpixel & (1 << 15))
{
// RGB5

View File

@ -18,7 +18,6 @@
#include "WiiBanner.hpp"
#include "BinaryReader.hpp"
#include "BinaryWriter.hpp"
#include "IOException.hpp"
#include "aes.h"
#include "ec.h"
#include "utility.hpp"

View File

@ -225,7 +225,7 @@ WiiImage* WiiSaveReader::readImage(Uint32 width, Uint32 height)
{
Uint8* image = (Uint8*)base::readBytes(width*height*2);
if (!isEmpty((Int8*)image, width*height*2))
if (!utility::isEmpty((Int8*)image, width*height*2))
return new WiiImage(width, height, image);
return NULL;

View File

@ -167,15 +167,15 @@ Uint32 WiiSaveWriter::writeFile(WiiFile *file)
base::writeByte(file->type());
Uint8 name[0x45];
fillRandom(name, 0x45);
utility::fillRandom(name, 0x45);
memcpy(name, file->filename().c_str(), file->filename().size());
name[file->filename().size()] = '\0';
base::writeBytes((Int8*)name, 0x45);
Uint8 iv[16];
fillRandom(iv, 0x10);
utility::fillRandom(iv, 0x10);
base::writeBytes((Int8*)iv, 0x10);
Uint8 crap[0x20];
fillRandom(crap, 0x20);
utility::fillRandom(crap, 0x20);
base::writeBytes((Int8*)crap, 0x20);
if (file->type() == WiiFile::File)
@ -245,8 +245,8 @@ void WiiSaveWriter::writeCerts(Uint32 filesSize, Uint32 ngId, Uint8 *ngPriv, Uin
generate_ecdsa(sig, sig+30, apPriv, hash2);
int stuff = 0x2f536969;
if (!isSystemBigEndian())
stuff = swap32(stuff);
if (!utility::isSystemBigEndian())
stuff = utility::swap32(stuff);
*(Uint32*)(sig+60) = stuff;
delete[] hash2;

View File

@ -13,21 +13,21 @@
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "ZQuest.hpp"
#include "ZQuestFile.hpp"
namespace zelda
{
const Uint32 ZQuest::Major = 1;
const Uint32 ZQuest::Minor = 0;
const Uint32 ZQuest::Revision = 0;
const Uint32 ZQuest::Build = 0;
const Uint32 ZQuestFile::Major = 1;
const Uint32 ZQuestFile::Minor = 0;
const Uint32 ZQuestFile::Revision = 0;
const Uint32 ZQuestFile::Build = 0;
const Uint32 ZQuest::Version = Major | (Minor << 8) | (Revision << 16) | (Build << 24);
const Uint32 ZQuestFile::Version = Major | (Minor << 8) | (Revision << 16) | (Build << 24);
const Uint32 ZQuest::Magic = 'Z' | ('Q' << 8) | ('S' << 16) | ('1' << 24);
const Uint32 ZQuestFile::Magic = 'Z' | ('Q' << 8) | ('S' << 16) | ('1' << 24);
ZQuest::ZQuest()
ZQuestFile::ZQuestFile()
: m_game(NoGame),
m_endian(LittleEndian),
m_data(NULL),
@ -36,7 +36,7 @@ ZQuest::ZQuest()
initGameStrings();
}
ZQuest::ZQuest(ZQuest::Game game, Endian endian, Uint8* data, Uint32 length)
ZQuestFile::ZQuestFile(ZQuestFile::Game game, Endian endian, Uint8* data, Uint32 length)
: m_game(game),
m_endian(endian),
m_data(data),
@ -45,34 +45,34 @@ ZQuest::ZQuest(ZQuest::Game game, Endian endian, Uint8* data, Uint32 length)
initGameStrings();
}
ZQuest::~ZQuest()
ZQuestFile::~ZQuestFile()
{
delete[] m_data;
m_data = NULL;
m_length = 0;
}
void ZQuest::setGame(ZQuest::Game game)
void ZQuestFile::setGame(ZQuestFile::Game game)
{
m_game = game;
}
ZQuest::Game ZQuest::game() const
ZQuestFile::Game ZQuestFile::game() const
{
return m_game;
}
void ZQuest::setEndian(Endian endian)
void ZQuestFile::setEndian(Endian endian)
{
m_endian = endian;
}
Endian ZQuest::endian() const
Endian ZQuestFile::endian() const
{
return m_endian;
}
void ZQuest::setData(Uint8* data)
void ZQuestFile::setData(Uint8* data, Uint32 length)
{
// ensure we're not overwritting our data without freeing first
// or assigning unnecessisarily
@ -80,25 +80,22 @@ void ZQuest::setData(Uint8* data)
{
delete[] m_data;
m_data = data;
m_length = length;
}
}
Uint8* ZQuest::data() const
Uint8* ZQuestFile::data() const
{
return m_data;
}
void ZQuest::setLength(Uint32 length)
{
m_length = length;
}
Uint32 ZQuest::length() const
Uint32 ZQuestFile::length() const
{
return m_length;
}
std::string ZQuest::gameString() const
std::string ZQuestFile::gameString() const
{
if (m_game > m_gameStrings.size() - 1)
return "Unsupported Game";
@ -106,7 +103,7 @@ std::string ZQuest::gameString() const
return m_gameStrings[m_game];
}
void ZQuest::initGameStrings()
void ZQuestFile::initGameStrings()
{
m_gameStrings.push_back("No Game");
m_gameStrings.push_back("Legend Of Zelda");

View File

@ -14,7 +14,7 @@
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "ZQuestFileReader.hpp"
#include "ZQuest.hpp"
#include "ZQuestFile.hpp"
#include "InvalidOperationException.hpp"
#include "Compression.hpp"
@ -33,26 +33,26 @@ ZQuestFileReader::ZQuestFileReader(const std::string &filename)
{
}
ZQuest *ZQuestFileReader::read()
ZQuestFile *ZQuestFileReader::read()
{
Uint32 magic, version, compressedLen, uncompressedLen;
ZQuest::Game game;
ZQuestFile::Game game;
Uint16 BOM;
Uint8* data;
magic = base::readUInt32();
if (magic != ZQuest::Magic)
if (magic != ZQuestFile::Magic)
throw error::InvalidOperationException("ZQuestFileReader::read -> Not a valid ZQuest file");
version = base::readUInt32();
if (version != ZQuest::Version)
if (version != ZQuestFile::Version)
throw error::InvalidOperationException("ZQuestFileReader::read -> Unsupported ZQuest version");
compressedLen = base::readUInt32();
uncompressedLen = base::readUInt32();
game = (ZQuest::Game)base::readUInt32();
game = (ZQuestFile::Game)base::readUInt32();
BOM = base::readUInt16();
base::seek(0x0A);
data = (Uint8*)base::readBytes(compressedLen); // compressedLen is always the total file size
@ -73,7 +73,7 @@ ZQuest *ZQuestFileReader::read()
data = dst;
}
return new ZQuest(game, BOM == 0xFEFF ? BigEndian : LittleEndian, data, uncompressedLen);
return new ZQuestFile(game, BOM == 0xFEFF ? BigEndian : LittleEndian, data, uncompressedLen);
}
} // io

View File

@ -15,7 +15,7 @@
#include "ZQuestFileWriter.hpp"
#include "InvalidOperationException.hpp"
#include "ZQuest.hpp"
#include "ZQuestFile.hpp"
#include "Compression.hpp"
namespace zelda
@ -33,22 +33,23 @@ ZQuestFileWriter::ZQuestFileWriter(const std::string& filename)
{
}
void ZQuestFileWriter::write(ZQuest* quest, bool compress)
void ZQuestFileWriter::write(ZQuestFile* quest, bool compress)
{
if (!quest)
throw error::InvalidOperationException("ZQuestFileWriter::writer -> quest cannot be NULL");
throw error::InvalidOperationException("ZQuestFileWriter::write -> quest cannot be NULL");
base::writeUInt32(ZQuest::Magic);
base::writeUInt32(ZQuest::Version);
base::writeUInt32(ZQuestFile::Magic);
base::writeUInt32(ZQuestFile::Version);
Uint8* questData = quest->data();
Uint32 compLen = quest->length();
Uint32 compLen;
if (compress)
{
Uint8* compData = new Uint8[quest->length() + 0x20]; // add 20 bytes because sometimes the file grows with compression
io::Compression::compressZlib(questData, quest->length(), compData, &compLen);
Uint8* compData = new Uint8[quest->length() + 0x40]; // add 20 bytes because sometimes the file grows with compression
compLen = quest->length() + 0x40;
compLen = io::Compression::compressZlib(questData, quest->length(), compData, compLen);
// if the compressed data is the same length or larger than the original data, just store the original
if (compLen >= quest->length())
if (compLen >= quest->length() || compLen <= 0)
{
compLen = quest->length();
// Delete the compressed data since we won't be using it
@ -64,7 +65,10 @@ void ZQuestFileWriter::write(ZQuest* quest, bool compress)
}
}
else
{
compLen = quest->length();
base::writeUInt32(quest->length());
}
base::writeUInt32(quest->length());
base::writeUInt32(quest->game());
@ -73,6 +77,12 @@ void ZQuestFileWriter::write(ZQuest* quest, bool compress)
base::writeUBytes(questData, compLen);
base::save();
// Delete compressed data to preven memory leaks
if (questData != quest->data())
{
delete[] questData;
questData = NULL;
}
}
} // io

130
src/aes.c
View File

@ -8,15 +8,11 @@
algorithm place on its exploitation.
*/
#include "aes.h"
#include <stdio.h>
//#include <stdlib.h>
#include <string.h>
typedef unsigned char u8; /* 8 bits */
typedef unsigned long u32; /* 32 bits */
typedef unsigned long long u64;
/* rotates x one bit to the left */
#define ROTL(x) (((x)>>7)|((x)<<1))
@ -29,38 +25,38 @@ typedef unsigned long long u64;
/* Fixed Data */
static u8 InCo[4]={0xB,0xD,0x9,0xE}; /* Inverse Coefficients */
static Uint8 InCo[4]={0xB,0xD,0x9,0xE}; /* Inverse Coefficients */
static u8 fbsub[256];
static u8 rbsub[256];
static u8 ptab[256],ltab[256];
static u32 ftable[256];
static u32 rtable[256];
static u32 rco[30];
static Uint8 fbsub[256];
static Uint8 rbsub[256];
static Uint8 ptab[256],ltab[256];
static Uint32 ftable[256];
static Uint32 rtable[256];
static Uint32 rco[30];
/* Parameter-dependent data */
int Nk,Nb,Nr;
u8 fi[24],ri[24];
u32 fkey[120];
u32 rkey[120];
Uint8 fi[24],ri[24];
Uint32 fkey[120];
Uint32 rkey[120];
static u32 pack(u8 *b)
static Uint32 pack(const Uint8 *b)
{ /* pack bytes into a 32-bit Word */
return ((u32)b[3]<<24)|((u32)b[2]<<16)|((u32)b[1]<<8)|(u32)b[0];
return ((Uint32)b[3]<<24)|((Uint32)b[2]<<16)|((Uint32)b[1]<<8)|(Uint32)b[0];
}
static void unpack(u32 a,u8 *b)
static void unpack(Uint32 a,Uint8 *b)
{ /* unpack bytes from a word */
b[0]=(u8)a;
b[1]=(u8)(a>>8);
b[2]=(u8)(a>>16);
b[3]=(u8)(a>>24);
b[0]=(Uint8)a;
b[1]=(Uint8)(a>>8);
b[2]=(Uint8)(a>>16);
b[3]=(Uint8)(a>>24);
}
static u8 xtime(u8 a)
static Uint8 xtime(Uint8 a)
{
u8 b;
Uint8 b;
if (a&0x80) b=0x1B;
else b=0;
a<<=1;
@ -68,15 +64,15 @@ static u8 xtime(u8 a)
return a;
}
static u8 bmul(u8 x,u8 y)
static Uint8 bmul(Uint8 x,Uint8 y)
{ /* x.y= AntiLog(Log(x) + Log(y)) */
if (x && y) return ptab[(ltab[x]+ltab[y])%255];
else return 0;
}
static u32 SubByte(u32 a)
static Uint32 SubByte(Uint32 a)
{
u8 b[4];
Uint8 b[4];
unpack(a,b);
b[0]=fbsub[b[0]];
b[1]=fbsub[b[1]];
@ -85,18 +81,18 @@ static u32 SubByte(u32 a)
return pack(b);
}
static u8 product(u32 x,u32 y)
static Uint8 product(Uint32 x,Uint32 y)
{ /* dot product of two 4-byte arrays */
u8 xb[4],yb[4];
Uint8 xb[4],yb[4];
unpack(x,xb);
unpack(y,yb);
return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]);
}
static u32 InvMixCol(u32 x)
static Uint32 InvMixCol(Uint32 x)
{ /* matrix Multiplication */
u32 y,m;
u8 b[4];
Uint32 y,m;
Uint8 b[4];
m=pack(InCo);
b[3]=product(m,x);
@ -110,9 +106,9 @@ static u32 InvMixCol(u32 x)
return y;
}
u8 ByteSub(u8 x)
Uint8 ByteSub(Uint8 x)
{
u8 y=ptab[255-ltab[x]]; /* multiplicative inverse */
Uint8 y=ptab[255-ltab[x]]; /* multiplicative inverse */
x=y; x=ROTL(x);
y^=x; x=ROTL(x);
y^=x; x=ROTL(x);
@ -124,7 +120,7 @@ u8 ByteSub(u8 x)
void gentables(void)
{ /* generate tables */
int i;
u8 y,b[4];
Uint8 y,b[4];
/* use 3 as primitive root to generate power and log tables */
@ -143,7 +139,7 @@ void gentables(void)
rbsub[0x63]=0;
for (i=1;i<256;i++)
{
y=ByteSub((u8)i);
y=ByteSub((Uint8)i);
fbsub[i]=y; rbsub[y]=i;
}
@ -168,14 +164,14 @@ void gentables(void)
}
}
void gkey(int nb,int nk,u8 *key)
void gkey(int nb,int nk, const Uint8 *key)
{ /* blocksize=32*nb bits. Key=32*nk bits */
/* currently nb,bk = 4, 6 or 8 */
/* key comes as 4*Nk bytes */
/* Key Scheduler. Create expanded encryption key */
int i,j,k,m,N;
int C1,C2,C3;
u32 CipherKey[8];
Uint32 CipherKey[8];
Nb=nb; Nk=nk;
@ -240,10 +236,10 @@ void gkey(int nb,int nk,u8 *key)
* Instead of just one ftable[], I could have 4, the other *
* 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
void encrypt(u8 *buff)
void encrypt(Uint8 *buff)
{
int i,j,k,m;
u32 a[8],b[8],*x,*y,*t;
Uint32 a[8],b[8],*x,*y,*t;
for (i=j=0;i<Nb;i++,j+=4)
{
@ -263,10 +259,10 @@ void encrypt(u8 *buff)
for (m=j=0;j<Nb;j++,m+=3)
{ /* deal with each 32-bit element of the State */
/* This is the time-critical bit */
y[j]=fkey[k++]^ftable[(u8)x[j]]^
ROTL8(ftable[(u8)(x[fi[m]]>>8)])^
ROTL16(ftable[(u8)(x[fi[m+1]]>>16)])^
ROTL24(ftable[(u8)(x[fi[m+2]]>>24)]);
y[j]=fkey[k++]^ftable[(Uint8)x[j]]^
ROTL8(ftable[(Uint8)(x[fi[m]]>>8)])^
ROTL16(ftable[(Uint8)(x[fi[m+1]]>>16)])^
ROTL24(ftable[(Uint8)(x[fi[m+2]]>>24)]);
}
t=x; x=y; y=t; /* swap pointers */
}
@ -274,23 +270,23 @@ void encrypt(u8 *buff)
/* Last Round - unroll if possible */
for (m=j=0;j<Nb;j++,m+=3)
{
y[j]=fkey[k++]^(u32)fbsub[(u8)x[j]]^
ROTL8((u32)fbsub[(u8)(x[fi[m]]>>8)])^
ROTL16((u32)fbsub[(u8)(x[fi[m+1]]>>16)])^
ROTL24((u32)fbsub[(u8)(x[fi[m+2]]>>24)]);
y[j]=fkey[k++]^(Uint32)fbsub[(Uint8)x[j]]^
ROTL8((Uint32)fbsub[(Uint8)(x[fi[m]]>>8)])^
ROTL16((Uint32)fbsub[(Uint8)(x[fi[m+1]]>>16)])^
ROTL24((Uint32)fbsub[(Uint8)(x[fi[m+2]]>>24)]);
}
for (i=j=0;i<Nb;i++,j+=4)
{
unpack(y[i],(u8 *)&buff[j]);
unpack(y[i],(Uint8 *)&buff[j]);
x[i]=y[i]=0; /* clean up stack */
}
return;
}
void decrypt(u8 *buff)
void decrypt(Uint8 *buff)
{
int i,j,k,m;
u32 a[8],b[8],*x,*y,*t;
Uint32 a[8],b[8],*x,*y,*t;
for (i=j=0;i<Nb;i++,j+=4)
{
@ -309,10 +305,10 @@ void decrypt(u8 *buff)
for (m=j=0;j<Nb;j++,m+=3)
{ /* This is the time-critical bit */
y[j]=rkey[k++]^rtable[(u8)x[j]]^
ROTL8(rtable[(u8)(x[ri[m]]>>8)])^
ROTL16(rtable[(u8)(x[ri[m+1]]>>16)])^
ROTL24(rtable[(u8)(x[ri[m+2]]>>24)]);
y[j]=rkey[k++]^rtable[(Uint8)x[j]]^
ROTL8(rtable[(Uint8)(x[ri[m]]>>8)])^
ROTL16(rtable[(Uint8)(x[ri[m+1]]>>16)])^
ROTL24(rtable[(Uint8)(x[ri[m+2]]>>24)]);
}
t=x; x=y; y=t; /* swap pointers */
}
@ -320,28 +316,28 @@ void decrypt(u8 *buff)
/* Last Round - unroll if possible */
for (m=j=0;j<Nb;j++,m+=3)
{
y[j]=rkey[k++]^(u32)rbsub[(u8)x[j]]^
ROTL8((u32)rbsub[(u8)(x[ri[m]]>>8)])^
ROTL16((u32)rbsub[(u8)(x[ri[m+1]]>>16)])^
ROTL24((u32)rbsub[(u8)(x[ri[m+2]]>>24)]);
y[j]=rkey[k++]^(Uint32)rbsub[(Uint8)x[j]]^
ROTL8((Uint32)rbsub[(Uint8)(x[ri[m]]>>8)])^
ROTL16((Uint32)rbsub[(Uint8)(x[ri[m+1]]>>16)])^
ROTL24((Uint32)rbsub[(Uint8)(x[ri[m+2]]>>24)]);
}
for (i=j=0;i<Nb;i++,j+=4)
{
unpack(y[i],(u8 *)&buff[j]);
unpack(y[i],(Uint8 *)&buff[j]);
x[i]=y[i]=0; /* clean up stack */
}
return;
}
void aes_set_key(u8 *key) {
void aes_set_key(const Uint8 *key) {
gentables();
gkey(4, 4, key);
}
// CBC mode decryption
void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len) {
u8 block[16];
u8* ctext_ptr;
void aes_decrypt(Uint8 *iv, const Uint8 *inbuf, Uint8 *outbuf, Uint64 len) {
Uint8 block[16];
Uint8* ctext_ptr;
unsigned int blockno = 0, i;
//fprintf( stderr,"aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len );
@ -359,7 +355,7 @@ void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len) {
memcpy(block, inbuf + blockno * sizeof(block), fraction);
decrypt(block);
if (blockno == 0) ctext_ptr = iv;
else ctext_ptr = inbuf + (blockno-1) * sizeof(block);
else ctext_ptr = (Uint8*)(inbuf + (blockno-1) * sizeof(block));
for(i=0; i < fraction; i++)
outbuf[blockno * sizeof(block) + i] =
@ -370,8 +366,8 @@ void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len) {
}
// CBC mode encryption
void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len) {
u8 block[16];
void aes_encrypt(Uint8 *iv, const Uint8 *inbuf, Uint8 *outbuf, Uint64 len) {
Uint8 block[16];
unsigned int blockno = 0, i;
//printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);

View File

@ -321,14 +321,6 @@ static void point_mul(Uint8 *d, Uint8 *a, Uint8 *b) // a is bignum
}
}
// DUPE FUNCTION! NUKE IT!!
void sillyRandom(Uint8 * rndArea, Uint8 count)
{
for(Uint16 i = 0; i < count; i++)
rndArea[i]=rand();
}
void generate_ecdsa(Uint8 *R, Uint8 *S, Uint8 *k, Uint8 *hash)
{
Uint8 e[30];
@ -341,7 +333,7 @@ void generate_ecdsa(Uint8 *R, Uint8 *S, Uint8 *k, Uint8 *hash)
elt_zero(e);
memcpy(e + 10, hash, 20);
sillyRandom(m, sizeof(m));
zelda::utility::fillRandom(m, sizeof(m));
m[0] = 0;
// R = (mG).x
@ -416,11 +408,11 @@ bool check_ec(Uint8 *ng, Uint8 *ap, Uint8 *sig, Uint8 *sig_hash)
void make_ec_cert(Uint8 *cert, Uint8 *sig, char *signer, char *name, Uint8 *priv, Uint32 key_id )
{
memset(cert, 0, 0x180);
*(Uint32*)(cert) = swapU32(0x10002);
*(Uint32*)(cert) = zelda::utility::swapU32(0x10002);
memcpy((char*)cert + 4, sig, 60);
strcpy((char*)cert + 0x80, signer);
*(Uint32*)(cert + 0xc0) = swapU32(2);
*(Uint32*)(cert + 0xc0) = zelda::utility::swapU32(2);
strcpy((char*)cert + 0xc4, name);
*(Uint32*)(cert + 0x104) = swapU32(key_id);
*(Uint32*)(cert + 0x104) = zelda::utility::swapU32(key_id);
ec_priv_to_pub(priv, cert + 0x108);
}

View File

@ -386,8 +386,8 @@ Uint8* getSha1( Uint8 * stuff, Uint32 stuff_size )
for( int i = 0; i < 5 ; i++ )
{
int val = sha.Message_Digest[ i ];
if (!isSystemBigEndian())
val = swap32(val);
if (!zelda::utility::isSystemBigEndian())
val = zelda::utility::swap32(val);
memcpy( (char*)ret + ( i * 4 ), &val, 4 );
}

View File

@ -18,57 +18,65 @@
#include <string.h>
#include <stdlib.h>
bool isEmpty(Int8* buf, size_t size)
namespace zelda
{
namespace utility
{
bool isEmpty(Int8* buf, Uint32 size)
{
return buf[0] == 0 && !memcmp(buf, buf + 1, size - 1);
}
unsigned short swapU16(unsigned short val )
Uint16 swapU16(Uint16 val )
{
return (val << 8) | (val >> 8 );
return (Uint16)swap16(val);
}
short swap16(short val )
Int16 swap16(Int16 val )
{
return (val << 8) | ((val >> 8) & 0xFF);
}
unsigned int swapU32(unsigned int val)
Uint32 swapU32(Uint32 val)
{
val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8;
return (Uint32)val;
return (Uint32)swap32(val);
}
int swap32( int val )
int swap32(Int32 val )
{
val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8;
return val;
}
long long swap64(long long val)
Uint64 swapU64(Uint64 val)
{
return ((long long)((((long long)(val) & 0xFF00000000000000ULL) >> 56) |
(((long long)(val) & 0x00FF000000000000ULL) >> 40) |
(((long long)(val) & 0x0000FF0000000000ULL) >> 24) |
(((long long)(val) & 0x000000FF00000000ULL) >> 8) |
(((long long)(val) & 0x00000000FF000000ULL) << 8) |
(((long long)(val) & 0x0000000000FF0000ULL) << 24) |
(((long long)(val) & 0x000000000000FF00ULL) << 40) |
(((long long)(val) & 0x00000000000000FFULL) << 56)));
return (Uint64)swap64(val);
}
Int64 swap64(Int64 val)
{
return ((Int64)((((Int64)(val) & 0xFF00000000000000ULL) >> 56) |
(((Int64)(val) & 0x00FF000000000000ULL) >> 40) |
(((Int64)(val) & 0x0000FF0000000000ULL) >> 24) |
(((Int64)(val) & 0x000000FF00000000ULL) >> 8) |
(((Int64)(val) & 0x00000000FF000000ULL) << 8) |
(((Int64)(val) & 0x0000000000FF0000ULL) << 24) |
(((Int64)(val) & 0x000000000000FF00ULL) << 40) |
(((Int64)(val) & 0x00000000000000FFULL) << 56)));
}
bool isSystemBigEndian()
{
char* test = (char*)"\xFE\xFF";
return (*(unsigned short*)test == 0xFEFF);
Uint8* test = (Uint8*)"\xFE\xFF";
return (*(Uint16*)test == 0xFEFF);
}
void fillRandom(Uint8 * rndArea, Uint8 count)
{
for(Uint16 i = 0; i < count; i++)
rndArea[i]=rand();
for(Uint16 i = 0; i < count; i++)
rndArea[i]=rand();
}
float swapFloat(float val)
@ -108,57 +116,60 @@ double swapDouble(double val)
//the second 4 bytes in the Yaz0 header).
void yaz0Decode(Uint8* src, Uint8* dst, Uint32 uncompressedSize)
{
Uint32 srcPlace = 0, dstPlace = 0; //current read/write positions
Uint32 srcPlace = 0, dstPlace = 0; //current read/write positions
Int32 validBitCount = 0; //number of valid bits left in "code" byte
Uint8 currCodeByte;
while(dstPlace < uncompressedSize)
{
//read new "code" byte if the current one is used up
if(validBitCount == 0)
Int32 validBitCount = 0; //number of valid bits left in "code" byte
Uint8 currCodeByte;
while(dstPlace < uncompressedSize)
{
currCodeByte = src[srcPlace];
++srcPlace;
validBitCount = 8;
//read new "code" byte if the current one is used up
if(validBitCount == 0)
{
currCodeByte = src[srcPlace];
++srcPlace;
validBitCount = 8;
}
if((currCodeByte & 0x80) != 0)
{
//straight copy
dst[dstPlace] = src[srcPlace];
dstPlace++;
srcPlace++;
}
else
{
//RLE part
Uint8 byte1 = src[srcPlace];
Uint8 byte2 = src[srcPlace + 1];
srcPlace += 2;
Uint32 dist = ((byte1 & 0xF) << 8) | byte2;
Uint32 copySource = dstPlace - (dist + 1);
Uint32 numBytes = byte1 >> 4;
if(numBytes == 0)
{
numBytes = src[srcPlace] + 0x12;
srcPlace++;
}
else
numBytes += 2;
//copy run
for(Uint32 i = 0; i < numBytes; ++i)
{
dst[dstPlace] = dst[copySource];
copySource++;
dstPlace++;
}
}
//use next bit from "code" byte
currCodeByte <<= 1;
validBitCount-=1;
}
if((currCodeByte & 0x80) != 0)
{
//straight copy
dst[dstPlace] = src[srcPlace];
dstPlace++;
srcPlace++;
}
else
{
//RLE part
Uint8 byte1 = src[srcPlace];
Uint8 byte2 = src[srcPlace + 1];
srcPlace += 2;
Uint32 dist = ((byte1 & 0xF) << 8) | byte2;
Uint32 copySource = dstPlace - (dist + 1);
Uint32 numBytes = byte1 >> 4;
if(numBytes == 0)
{
numBytes = src[srcPlace] + 0x12;
srcPlace++;
}
else
numBytes += 2;
//copy run
for(Uint32 i = 0; i < numBytes; ++i)
{
dst[dstPlace] = dst[copySource];
copySource++;
dstPlace++;
}
}
//use next bit from "code" byte
currCodeByte <<= 1;
validBitCount-=1;
}
}
} // utility
} // zelda