* 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" #include "Types.hpp"
namespace zelda
{
enum BowType : char enum BowType : char
{ {
BowNone, BowNone,
@ -105,5 +108,6 @@ enum ALTTPTagAlong
AfterBoss AfterBoss
}; };
} // zelda
#endif // __DOXYGEN_IGNORE__ #endif // __DOXYGEN_IGNORE__
#endif // __ALTTP_ENUMS_HPP__ #endif // __ALTTP_ENUMS_HPP__

View File

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

View File

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

View File

@ -138,6 +138,13 @@ public:
* \param str The string to write to the buffer * \param str The string to write to the buffer
*/ */
void writeUnicode(const std::string& str); 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: protected:
Int8 readByte(); Int8 readByte();
Int8* readBytes(Int64); Int8* readBytes(Int64);

View File

@ -25,7 +25,7 @@ namespace io
namespace Compression namespace Compression
{ {
Int32 decompressZlib(Uint8* src, Uint32 srcLen, Uint8* dst, Uint32 dstLen); 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. * all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class MCFileReader : public io::BinaryReader class MCFileReader : protected BinaryReader
{ {
BINARYREADER_BASE BINARYREADER_BASE
public: public:

View File

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

View File

@ -80,16 +80,16 @@ public:
* \throw IOException * \throw IOException
*/ */
virtual void writeBit(bool val); virtual void writeBit(bool val);
/*! \brief Writes a byte at the current position and advances the position by one byte. /*! \brief Writes a byte at the current position and advances the position by one byte.
* \param byte The value to write * \param byte The value to write
* \throw IOException * \throw IOException
*/ */
virtual void writeUByte(Uint8 byte); virtual void writeUByte(Uint8 byte);
/*! \brief Writes a byte at the current position and advances the position by one byte. /*! \brief Writes a byte at the current position and advances the position by one byte.
* \param byte The value to write * \param byte The value to write
* \throw IOException * \throw IOException
*/ */
virtual void writeByte(Int8 byte); virtual void writeByte(Int8 byte);
/*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length /*! \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> #include <limits.h>
#ifdef __cplusplus
namespace zelda
{
/*! \enum Endian /*! \enum Endian
* \brief Allows the user to specify the Endianness of data.<br /> * \brief Allows the user to specify the Endianness of data.<br />
* The proper actions are automatically taken depending on platform and * 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) LittleEndian, //!< Specifies that the Stream is Little Endian (LSB)
BigEndian //!< Specifies that the Stream is Big Endian (MSB) BigEndian //!< Specifies that the Stream is Big Endian (MSB)
}; };
} // zelda
#endif
// 8 bits integer types // 8 bits integer types
#if UCHAR_MAX == 0xFF #if UCHAR_MAX == 0xFF

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -105,8 +105,8 @@ void BinaryWriter::writeInt16(Int16 val)
else if (m_position > m_length) else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteInt16 -> Position outside stream bounds"); throw error::IOException("BinaryWriter::WriteInt16 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian)) if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = swap16(val); val = utility::swap16(val);
*(Int16*)(m_data + m_position) = val; *(Int16*)(m_data + m_position) = val;
m_position += sizeof(Int16); m_position += sizeof(Int16);
@ -126,8 +126,8 @@ void BinaryWriter::writeUInt16(Uint16 val)
throw error::IOException("BinaryWriter::WriteUInt16 -> Position outside stream bounds"); throw error::IOException("BinaryWriter::WriteUInt16 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian)) if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = swapU16(val); val = utility::swapU16(val);
*(Uint16*)(m_data + m_position) = val; *(Uint16*)(m_data + m_position) = val;
m_position += sizeof(Uint16); m_position += sizeof(Uint16);
@ -146,8 +146,8 @@ void BinaryWriter::writeInt32(Int32 val)
else if (m_position > m_length) else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteInt32 -> Position outside stream bounds"); throw error::IOException("BinaryWriter::WriteInt32 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian)) if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = swap32(val); val = utility::swap32(val);
*(Int32*)(m_data + m_position) = val; *(Int32*)(m_data + m_position) = val;
m_position += sizeof(Int32); m_position += sizeof(Int32);
@ -166,8 +166,8 @@ void BinaryWriter::writeUInt32(Uint32 val)
else if (m_position > m_length) else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteUInt32 -> Position outside stream bounds"); throw error::IOException("BinaryWriter::WriteUInt32 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian)) if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = swap32(val); val = utility::swapU32(val);
*(Uint32*)(m_data + m_position) = val; *(Uint32*)(m_data + m_position) = val;
m_position += sizeof(Uint32); m_position += sizeof(Uint32);
@ -187,8 +187,8 @@ void BinaryWriter::writeInt64(Int64 val)
throw error::IOException("BinaryWriter::WriteInt64 -> Position outside stream bounds"); throw error::IOException("BinaryWriter::WriteInt64 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian)) if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = swap64(val); val = utility::swap64(val);
*(Int64*)(m_data + m_position) = val; *(Int64*)(m_data + m_position) = val;
m_position += sizeof(Int64); m_position += sizeof(Int64);
@ -207,8 +207,8 @@ void BinaryWriter::writeUInt64(Uint64 val)
else if (m_position > m_length) else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteUInt64 -> Position outside stream bounds"); throw error::IOException("BinaryWriter::WriteUInt64 -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian)) if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = swap64(val); val = utility::swapU64(val);
*(Uint64*)(m_data + m_position) = val; *(Uint64*)(m_data + m_position) = val;
m_position += sizeof(Uint64); m_position += sizeof(Uint64);
@ -227,8 +227,8 @@ void BinaryWriter::writeFloat(float val)
else if (m_position > m_length) else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteFloat -> Position outside stream bounds"); throw error::IOException("BinaryWriter::WriteFloat -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian)) if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = swapFloat(val); val = utility::swapFloat(val);
*(float*)(m_data + m_position) = val; *(float*)(m_data + m_position) = val;
m_position += sizeof(float); m_position += sizeof(float);
@ -247,8 +247,8 @@ void BinaryWriter::writeDouble(double val)
else if (m_position > m_length) else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteDouble -> Position outside stream bounds"); throw error::IOException("BinaryWriter::WriteDouble -> Position outside stream bounds");
if ((!isSystemBigEndian() && m_endian == BigEndian) || (isSystemBigEndian() && m_endian == LittleEndian)) if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = swapDouble(val); val = utility::swapDouble(val);
*(double*)(m_data + m_position)= val; *(double*)(m_data + m_position)= val;
m_position += sizeof(double); 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() bool BinaryWriter::isOpenForReading()
{ {
return false; return false;

View File

@ -14,6 +14,8 @@
// along with libZelda. If not, see <http://www.gnu.org/licenses/> // along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "Compression.hpp" #include "Compression.hpp"
#include "Exception.hpp"
#include <iostream>
#include <zlib.h> #include <zlib.h>
@ -26,7 +28,7 @@ namespace Compression
Int32 decompressZlib(Uint8 *src, Uint32 srcLen, Uint8* dst, Uint32 dstLen) 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_in = strm.avail_in = srcLen;
strm.total_out = strm.avail_out = dstLen; strm.total_out = strm.avail_out = dstLen;
strm.next_in = (Bytef *) src; strm.next_in = (Bytef *) src;
@ -39,18 +41,20 @@ Int32 decompressZlib(Uint8 *src, Uint32 srcLen, Uint8* dst, Uint32 dstLen)
Int32 err = -1; Int32 err = -1;
Int32 ret = -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 err = inflateInit(&strm); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib
if (err == Z_OK) { if (err == Z_OK)
{
err = inflate(&strm, Z_FINISH); err = inflate(&strm, Z_FINISH);
if (err == Z_STREAM_END) { if (err == Z_STREAM_END)
ret = strm.total_out; ret = strm.total_out;
} else
else { {
inflateEnd(&strm); inflateEnd(&strm);
return err; return err;
} }
} }
else { else
{
inflateEnd(&strm); inflateEnd(&strm);
return err; return err;
} }
@ -60,9 +64,43 @@ Int32 decompressZlib(Uint8 *src, Uint32 srcLen, Uint8* dst, Uint32 dstLen)
return ret; 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 } // Compression

View File

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

View File

@ -156,9 +156,9 @@ std::vector<std::string> TextStream::readLines(Uint32 numLines)
std::string TextStream::readLineAt(Uint32 line) std::string TextStream::readLineAt(Uint32 line)
{ {
if (m_accessmode != ReadOnly && m_accessmode != ReadWrite) 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) 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()) if ((line - 1) >= m_lines.size())
throw error::IOException("TextStream::readLineAt -> Line index out of range"); 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)); Uint16 oldpixel = *(Uint16*)(m_data + ((iv++) * 2));
//if((x >= m_width) || (y >= m_height)) //if((x >= m_width) || (y >= m_height))
// continue; // continue;
oldpixel = swapU16(oldpixel); oldpixel = utility::swapU16(oldpixel);
if(oldpixel & (1 << 15)) if(oldpixel & (1 << 15))
{ {
// RGB5 // RGB5

View File

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

View File

@ -225,7 +225,7 @@ WiiImage* WiiSaveReader::readImage(Uint32 width, Uint32 height)
{ {
Uint8* image = (Uint8*)base::readBytes(width*height*2); 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 new WiiImage(width, height, image);
return NULL; return NULL;

View File

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

View File

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

View File

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

View File

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

130
src/aes.c
View File

@ -8,15 +8,11 @@
algorithm place on its exploitation. algorithm place on its exploitation.
*/ */
#include "aes.h"
#include <stdio.h> #include <stdio.h>
//#include <stdlib.h> //#include <stdlib.h>
#include <string.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 */ /* rotates x one bit to the left */
#define ROTL(x) (((x)>>7)|((x)<<1)) #define ROTL(x) (((x)>>7)|((x)<<1))
@ -29,38 +25,38 @@ typedef unsigned long long u64;
/* Fixed Data */ /* 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 Uint8 fbsub[256];
static u8 rbsub[256]; static Uint8 rbsub[256];
static u8 ptab[256],ltab[256]; static Uint8 ptab[256],ltab[256];
static u32 ftable[256]; static Uint32 ftable[256];
static u32 rtable[256]; static Uint32 rtable[256];
static u32 rco[30]; static Uint32 rco[30];
/* Parameter-dependent data */ /* Parameter-dependent data */
int Nk,Nb,Nr; int Nk,Nb,Nr;
u8 fi[24],ri[24]; Uint8 fi[24],ri[24];
u32 fkey[120]; Uint32 fkey[120];
u32 rkey[120]; Uint32 rkey[120];
static u32 pack(u8 *b) static Uint32 pack(const Uint8 *b)
{ /* pack bytes into a 32-bit Word */ { /* 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 */ { /* unpack bytes from a word */
b[0]=(u8)a; b[0]=(Uint8)a;
b[1]=(u8)(a>>8); b[1]=(Uint8)(a>>8);
b[2]=(u8)(a>>16); b[2]=(Uint8)(a>>16);
b[3]=(u8)(a>>24); b[3]=(Uint8)(a>>24);
} }
static u8 xtime(u8 a) static Uint8 xtime(Uint8 a)
{ {
u8 b; Uint8 b;
if (a&0x80) b=0x1B; if (a&0x80) b=0x1B;
else b=0; else b=0;
a<<=1; a<<=1;
@ -68,15 +64,15 @@ static u8 xtime(u8 a)
return a; return a;
} }
static u8 bmul(u8 x,u8 y) static Uint8 bmul(Uint8 x,Uint8 y)
{ /* x.y= AntiLog(Log(x) + Log(y)) */ { /* x.y= AntiLog(Log(x) + Log(y)) */
if (x && y) return ptab[(ltab[x]+ltab[y])%255]; if (x && y) return ptab[(ltab[x]+ltab[y])%255];
else return 0; else return 0;
} }
static u32 SubByte(u32 a) static Uint32 SubByte(Uint32 a)
{ {
u8 b[4]; Uint8 b[4];
unpack(a,b); unpack(a,b);
b[0]=fbsub[b[0]]; b[0]=fbsub[b[0]];
b[1]=fbsub[b[1]]; b[1]=fbsub[b[1]];
@ -85,18 +81,18 @@ static u32 SubByte(u32 a)
return pack(b); return pack(b);
} }
static u8 product(u32 x,u32 y) static Uint8 product(Uint32 x,Uint32 y)
{ /* dot product of two 4-byte arrays */ { /* dot product of two 4-byte arrays */
u8 xb[4],yb[4]; Uint8 xb[4],yb[4];
unpack(x,xb); unpack(x,xb);
unpack(y,yb); unpack(y,yb);
return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]); 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 */ { /* matrix Multiplication */
u32 y,m; Uint32 y,m;
u8 b[4]; Uint8 b[4];
m=pack(InCo); m=pack(InCo);
b[3]=product(m,x); b[3]=product(m,x);
@ -110,9 +106,9 @@ static u32 InvMixCol(u32 x)
return y; 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); x=y; x=ROTL(x);
y^=x; x=ROTL(x); y^=x; x=ROTL(x);
y^=x; x=ROTL(x); y^=x; x=ROTL(x);
@ -124,7 +120,7 @@ u8 ByteSub(u8 x)
void gentables(void) void gentables(void)
{ /* generate tables */ { /* generate tables */
int i; int i;
u8 y,b[4]; Uint8 y,b[4];
/* use 3 as primitive root to generate power and log tables */ /* use 3 as primitive root to generate power and log tables */
@ -143,7 +139,7 @@ void gentables(void)
rbsub[0x63]=0; rbsub[0x63]=0;
for (i=1;i<256;i++) for (i=1;i<256;i++)
{ {
y=ByteSub((u8)i); y=ByteSub((Uint8)i);
fbsub[i]=y; rbsub[y]=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 */ { /* blocksize=32*nb bits. Key=32*nk bits */
/* currently nb,bk = 4, 6 or 8 */ /* currently nb,bk = 4, 6 or 8 */
/* key comes as 4*Nk bytes */ /* key comes as 4*Nk bytes */
/* Key Scheduler. Create expanded encryption key */ /* Key Scheduler. Create expanded encryption key */
int i,j,k,m,N; int i,j,k,m,N;
int C1,C2,C3; int C1,C2,C3;
u32 CipherKey[8]; Uint32 CipherKey[8];
Nb=nb; Nk=nk; 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 * * Instead of just one ftable[], I could have 4, the other *
* 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */ * 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
void encrypt(u8 *buff) void encrypt(Uint8 *buff)
{ {
int i,j,k,m; 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) 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) for (m=j=0;j<Nb;j++,m+=3)
{ /* deal with each 32-bit element of the State */ { /* deal with each 32-bit element of the State */
/* This is the time-critical bit */ /* This is the time-critical bit */
y[j]=fkey[k++]^ftable[(u8)x[j]]^ y[j]=fkey[k++]^ftable[(Uint8)x[j]]^
ROTL8(ftable[(u8)(x[fi[m]]>>8)])^ ROTL8(ftable[(Uint8)(x[fi[m]]>>8)])^
ROTL16(ftable[(u8)(x[fi[m+1]]>>16)])^ ROTL16(ftable[(Uint8)(x[fi[m+1]]>>16)])^
ROTL24(ftable[(u8)(x[fi[m+2]]>>24)]); ROTL24(ftable[(Uint8)(x[fi[m+2]]>>24)]);
} }
t=x; x=y; y=t; /* swap pointers */ t=x; x=y; y=t; /* swap pointers */
} }
@ -274,23 +270,23 @@ void encrypt(u8 *buff)
/* Last Round - unroll if possible */ /* Last Round - unroll if possible */
for (m=j=0;j<Nb;j++,m+=3) for (m=j=0;j<Nb;j++,m+=3)
{ {
y[j]=fkey[k++]^(u32)fbsub[(u8)x[j]]^ y[j]=fkey[k++]^(Uint32)fbsub[(Uint8)x[j]]^
ROTL8((u32)fbsub[(u8)(x[fi[m]]>>8)])^ ROTL8((Uint32)fbsub[(Uint8)(x[fi[m]]>>8)])^
ROTL16((u32)fbsub[(u8)(x[fi[m+1]]>>16)])^ ROTL16((Uint32)fbsub[(Uint8)(x[fi[m+1]]>>16)])^
ROTL24((u32)fbsub[(u8)(x[fi[m+2]]>>24)]); ROTL24((Uint32)fbsub[(Uint8)(x[fi[m+2]]>>24)]);
} }
for (i=j=0;i<Nb;i++,j+=4) 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 */ x[i]=y[i]=0; /* clean up stack */
} }
return; return;
} }
void decrypt(u8 *buff) void decrypt(Uint8 *buff)
{ {
int i,j,k,m; 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) 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) for (m=j=0;j<Nb;j++,m+=3)
{ /* This is the time-critical bit */ { /* This is the time-critical bit */
y[j]=rkey[k++]^rtable[(u8)x[j]]^ y[j]=rkey[k++]^rtable[(Uint8)x[j]]^
ROTL8(rtable[(u8)(x[ri[m]]>>8)])^ ROTL8(rtable[(Uint8)(x[ri[m]]>>8)])^
ROTL16(rtable[(u8)(x[ri[m+1]]>>16)])^ ROTL16(rtable[(Uint8)(x[ri[m+1]]>>16)])^
ROTL24(rtable[(u8)(x[ri[m+2]]>>24)]); ROTL24(rtable[(Uint8)(x[ri[m+2]]>>24)]);
} }
t=x; x=y; y=t; /* swap pointers */ t=x; x=y; y=t; /* swap pointers */
} }
@ -320,28 +316,28 @@ void decrypt(u8 *buff)
/* Last Round - unroll if possible */ /* Last Round - unroll if possible */
for (m=j=0;j<Nb;j++,m+=3) for (m=j=0;j<Nb;j++,m+=3)
{ {
y[j]=rkey[k++]^(u32)rbsub[(u8)x[j]]^ y[j]=rkey[k++]^(Uint32)rbsub[(Uint8)x[j]]^
ROTL8((u32)rbsub[(u8)(x[ri[m]]>>8)])^ ROTL8((Uint32)rbsub[(Uint8)(x[ri[m]]>>8)])^
ROTL16((u32)rbsub[(u8)(x[ri[m+1]]>>16)])^ ROTL16((Uint32)rbsub[(Uint8)(x[ri[m+1]]>>16)])^
ROTL24((u32)rbsub[(u8)(x[ri[m+2]]>>24)]); ROTL24((Uint32)rbsub[(Uint8)(x[ri[m+2]]>>24)]);
} }
for (i=j=0;i<Nb;i++,j+=4) 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 */ x[i]=y[i]=0; /* clean up stack */
} }
return; return;
} }
void aes_set_key(u8 *key) { void aes_set_key(const Uint8 *key) {
gentables(); gentables();
gkey(4, 4, key); gkey(4, 4, key);
} }
// CBC mode decryption // CBC mode decryption
void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len) { void aes_decrypt(Uint8 *iv, const Uint8 *inbuf, Uint8 *outbuf, Uint64 len) {
u8 block[16]; Uint8 block[16];
u8* ctext_ptr; Uint8* ctext_ptr;
unsigned int blockno = 0, i; unsigned int blockno = 0, i;
//fprintf( stderr,"aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len ); //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); memcpy(block, inbuf + blockno * sizeof(block), fraction);
decrypt(block); decrypt(block);
if (blockno == 0) ctext_ptr = iv; 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++) for(i=0; i < fraction; i++)
outbuf[blockno * sizeof(block) + 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 // CBC mode encryption
void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len) { void aes_encrypt(Uint8 *iv, const Uint8 *inbuf, Uint8 *outbuf, Uint64 len) {
u8 block[16]; Uint8 block[16];
unsigned int blockno = 0, i; unsigned int blockno = 0, i;
//printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len); //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) void generate_ecdsa(Uint8 *R, Uint8 *S, Uint8 *k, Uint8 *hash)
{ {
Uint8 e[30]; Uint8 e[30];
@ -341,7 +333,7 @@ void generate_ecdsa(Uint8 *R, Uint8 *S, Uint8 *k, Uint8 *hash)
elt_zero(e); elt_zero(e);
memcpy(e + 10, hash, 20); memcpy(e + 10, hash, 20);
sillyRandom(m, sizeof(m)); zelda::utility::fillRandom(m, sizeof(m));
m[0] = 0; m[0] = 0;
// R = (mG).x // 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 ) void make_ec_cert(Uint8 *cert, Uint8 *sig, char *signer, char *name, Uint8 *priv, Uint32 key_id )
{ {
memset(cert, 0, 0x180); memset(cert, 0, 0x180);
*(Uint32*)(cert) = swapU32(0x10002); *(Uint32*)(cert) = zelda::utility::swapU32(0x10002);
memcpy((char*)cert + 4, sig, 60); memcpy((char*)cert + 4, sig, 60);
strcpy((char*)cert + 0x80, signer); strcpy((char*)cert + 0x80, signer);
*(Uint32*)(cert + 0xc0) = swapU32(2); *(Uint32*)(cert + 0xc0) = zelda::utility::swapU32(2);
strcpy((char*)cert + 0xc4, name); 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); 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++ ) for( int i = 0; i < 5 ; i++ )
{ {
int val = sha.Message_Digest[ i ]; int val = sha.Message_Digest[ i ];
if (!isSystemBigEndian()) if (!zelda::utility::isSystemBigEndian())
val = swap32(val); val = zelda::utility::swap32(val);
memcpy( (char*)ret + ( i * 4 ), &val, 4 ); memcpy( (char*)ret + ( i * 4 ), &val, 4 );
} }

View File

@ -18,57 +18,65 @@
#include <string.h> #include <string.h>
#include <stdlib.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); 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); return (val << 8) | ((val >> 8) & 0xFF);
} }
unsigned int swapU32(unsigned int val) Uint32 swapU32(Uint32 val)
{ {
val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16; return (Uint32)swap32(val);
val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8;
return (Uint32)val;
} }
int swap32( int val ) int swap32(Int32 val )
{ {
val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16; val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8; val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8;
return val; return val;
} }
long long swap64(long long val) Uint64 swapU64(Uint64 val)
{ {
return ((long long)((((long long)(val) & 0xFF00000000000000ULL) >> 56) | return (Uint64)swap64(val);
(((long long)(val) & 0x00FF000000000000ULL) >> 40) | }
(((long long)(val) & 0x0000FF0000000000ULL) >> 24) |
(((long long)(val) & 0x000000FF00000000ULL) >> 8) | Int64 swap64(Int64 val)
(((long long)(val) & 0x00000000FF000000ULL) << 8) | {
(((long long)(val) & 0x0000000000FF0000ULL) << 24) | return ((Int64)((((Int64)(val) & 0xFF00000000000000ULL) >> 56) |
(((long long)(val) & 0x000000000000FF00ULL) << 40) | (((Int64)(val) & 0x00FF000000000000ULL) >> 40) |
(((long long)(val) & 0x00000000000000FFULL) << 56))); (((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() bool isSystemBigEndian()
{ {
char* test = (char*)"\xFE\xFF"; Uint8* test = (Uint8*)"\xFE\xFF";
return (*(unsigned short*)test == 0xFEFF); return (*(Uint16*)test == 0xFEFF);
} }
void fillRandom(Uint8 * rndArea, Uint8 count) void fillRandom(Uint8 * rndArea, Uint8 count)
{ {
for(Uint16 i = 0; i < count; i++) for(Uint16 i = 0; i < count; i++)
rndArea[i]=rand(); rndArea[i]=rand();
} }
float swapFloat(float val) float swapFloat(float val)
@ -108,57 +116,60 @@ double swapDouble(double val)
//the second 4 bytes in the Yaz0 header). //the second 4 bytes in the Yaz0 header).
void yaz0Decode(Uint8* src, Uint8* dst, Uint32 uncompressedSize) 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 Int32 validBitCount = 0; //number of valid bits left in "code" byte
Uint8 currCodeByte; Uint8 currCodeByte;
while(dstPlace < uncompressedSize) while(dstPlace < uncompressedSize)
{
//read new "code" byte if the current one is used up
if(validBitCount == 0)
{ {
currCodeByte = src[srcPlace]; //read new "code" byte if the current one is used up
++srcPlace; if(validBitCount == 0)
validBitCount = 8; {
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