mirror of https://github.com/libAthena/athena.git
significant virtual-method refactor to streaming interface
This commit is contained in:
parent
ce917d4aca
commit
97dfabb265
14
.travis.yml
14
.travis.yml
|
@ -1,14 +0,0 @@
|
|||
compiler:
|
||||
- clang
|
||||
|
||||
before_install:
|
||||
- sudo add-apt-repository --yes "deb http://llvm.org/apt/precise/ llvm-toolchain-precise-3.6 main"
|
||||
- wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -;
|
||||
- sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa
|
||||
- sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq qt5-default clang-3.6
|
||||
|
||||
script:
|
||||
- qmake QMAKE_CXX=clang++-3.6 QMAKE_CC=clang-3.6 Athena.pro
|
||||
- make
|
|
@ -14,7 +14,7 @@ SOURCES += \
|
|||
$$PWD/src/ec.cpp \
|
||||
$$PWD/src/md5.cpp \
|
||||
$$PWD/src/sha1.cpp \
|
||||
$$PWD/src/aes.c
|
||||
$$PWD/src/aes.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/include/Athena/WiiBanner.hpp \
|
||||
|
@ -23,7 +23,7 @@ HEADERS += \
|
|||
$$PWD/include/Athena/WiiSave.hpp \
|
||||
$$PWD/include/Athena/WiiSaveReader.hpp \
|
||||
$$PWD/include/Athena/WiiSaveWriter.hpp \
|
||||
$$PWD/include/aes.h \
|
||||
$$PWD/include/aes.hpp \
|
||||
$$PWD/include/bn.h \
|
||||
$$PWD/include/ec.h \
|
||||
$$PWD/include/md5.h \
|
||||
|
|
|
@ -53,10 +53,6 @@ add_library(AthenaCore
|
|||
include/LZ77/LZLookupTable.hpp
|
||||
include/LZ77/LZType10.hpp
|
||||
include/LZ77/LZType11.hpp
|
||||
include/utf8.h
|
||||
include/utf8/checked.h
|
||||
include/utf8/core.h
|
||||
include/utf8/unchecked.h
|
||||
include/Athena/FileInfo.hpp
|
||||
include/Athena/Dir.hpp
|
||||
include/gekko_support.h
|
||||
|
@ -90,7 +86,7 @@ add_library(AthenaWiiSave
|
|||
src/ec.cpp
|
||||
src/md5.cpp
|
||||
src/sha1.cpp
|
||||
src/aes.c
|
||||
src/aes.cpp
|
||||
|
||||
include/Athena/WiiBanner.hpp
|
||||
include/Athena/WiiFile.hpp
|
||||
|
@ -98,12 +94,13 @@ add_library(AthenaWiiSave
|
|||
include/Athena/WiiSave.hpp
|
||||
include/Athena/WiiSaveReader.hpp
|
||||
include/Athena/WiiSaveWriter.hpp
|
||||
include/aes.h
|
||||
include/aes.hpp
|
||||
include/bn.h
|
||||
include/ec.h
|
||||
include/md5.h
|
||||
include/sha1.h
|
||||
)
|
||||
set_source_files_properties(src/aes.cpp PROPERTIES COMPILE_FLAGS -maes)
|
||||
|
||||
add_library(AthenaZelda
|
||||
src/Athena/ALTTPFile.cpp
|
||||
|
|
|
@ -17,64 +17,20 @@ public:
|
|||
inline const std::string& filename() const
|
||||
{return m_filename;}
|
||||
|
||||
inline void setEndian(Endian endian)
|
||||
{m_endian = endian;}
|
||||
inline Endian endian() const
|
||||
{return m_endian;}
|
||||
inline bool isBigEndian() const
|
||||
{return (m_endian == Endian::BigEndian);}
|
||||
inline bool isLittleEndian() const
|
||||
{return (m_endian == Endian::LittleEndian);}
|
||||
|
||||
void open();
|
||||
void close();
|
||||
inline bool isOpen() const
|
||||
{return m_fileHandle != NULL;}
|
||||
bool save();
|
||||
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
|
||||
inline void seekAlign32()
|
||||
{FileReader::seek(ROUND_UP_32(FileReader::position()), SeekOrigin::Begin);}
|
||||
bool atEnd() const;
|
||||
atUint64 position() const;
|
||||
atUint64 length() const;
|
||||
|
||||
|
||||
void seekBit(int);
|
||||
bool readBit();
|
||||
atUint8 readUByte();
|
||||
inline atInt8 readByte()
|
||||
{return (atInt8)FileReader::readUByte();}
|
||||
atUint8* readUBytes(atUint64 len);
|
||||
inline atInt8* readBytes(atUint64 len)
|
||||
{return (atInt8*)FileReader::readUBytes(len);}
|
||||
atUint64 readBytesToBuf(void* buf, atUint64 len)
|
||||
{return FileReader::readUBytesToBuf(buf, len);}
|
||||
atUint64 readUBytesToBuf(void* buf, atUint64 len);
|
||||
atUint16 readUint16();
|
||||
inline atInt16 readInt16()
|
||||
{return (atInt16)FileReader::readUint16();}
|
||||
atUint32 readUint32();
|
||||
inline atInt32 readInt32()
|
||||
{return (atInt32)FileReader::readUint32();}
|
||||
atUint64 readUint64();
|
||||
inline atInt64 readInt64()
|
||||
{return (atInt64)FileReader::readUint64();}
|
||||
double readDouble();
|
||||
float readFloat();
|
||||
inline bool readBool()
|
||||
{return (FileReader::readByte() != 0);}
|
||||
atVec3f readVec3f();
|
||||
atVec4f readVec4f();
|
||||
std::string readString(atInt32 fixedLen = -1);
|
||||
std::wstring readWString(atInt32 fixedLen = -1);
|
||||
std::string readUnicode(atInt32 fixedLen = -1);
|
||||
|
||||
protected:
|
||||
std::string m_filename;
|
||||
FILE* m_fileHandle;
|
||||
Endian m_endian;
|
||||
atUint8 m_currentByte;
|
||||
atUint8 m_bitShift;
|
||||
bool m_bitValid;
|
||||
atUint8 m_currentByte;
|
||||
};
|
||||
} // io
|
||||
} // Athena
|
||||
|
|
|
@ -14,62 +14,20 @@ public:
|
|||
FileWriter(const std::string& filename, bool overwrite = true);
|
||||
virtual ~FileWriter();
|
||||
|
||||
inline void setEndian(Endian endian)
|
||||
{m_endian = endian;}
|
||||
inline Endian endian() const
|
||||
{return m_endian;}
|
||||
inline bool isBigEndian() const
|
||||
{return (m_endian == Endian::BigEndian);}
|
||||
inline bool isLittleEndian() const
|
||||
{return (m_endian == Endian::LittleEndian);}
|
||||
|
||||
void open(bool overwrite = true);
|
||||
void close();
|
||||
inline bool isOpen() const
|
||||
{return m_fileHandle != NULL;}
|
||||
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
|
||||
inline void seekAlign32() {seek(ROUND_UP_32(position()), SeekOrigin::Begin);}
|
||||
bool atEnd() const;
|
||||
atUint64 position() const;
|
||||
atUint64 length() const;
|
||||
|
||||
void writeBit(bool val);
|
||||
void seekBit(int bit);
|
||||
void writeUByte(atUint8 val);
|
||||
inline void writeByte(atInt8 val)
|
||||
{FileWriter::writeUByte(val);}
|
||||
void writeUBytes(const atUint8* data, atUint64 len);
|
||||
void writeBytes(const atInt8* data, atUint64 len)
|
||||
{FileWriter::writeUBytes((atUint8*)data, len);}
|
||||
void writeUint16(atUint16 val);
|
||||
inline void writeInt16(atInt16 val)
|
||||
{FileWriter::writeUint16(val);}
|
||||
void writeUint32(atUint32 val);
|
||||
inline void writeInt32(atInt32 val)
|
||||
{FileWriter::writeUint32(val);}
|
||||
void writeUint64(atUint64 val);
|
||||
inline void writeInt64(atInt64 val)
|
||||
{FileWriter::writeUint64(val);}
|
||||
void writeDouble(double val);
|
||||
void writeFloat(float val);
|
||||
inline void writeBool(bool val)
|
||||
{FileWriter::writeByte(val);}
|
||||
void writeVec3f(atVec3f vec);
|
||||
void writeVec4f(atVec4f vec);
|
||||
void writeString(const std::string& val, atInt32 fixedLen = -1);
|
||||
void writeWString(const std::wstring& str, atInt32 fixedLen = -1);
|
||||
void writeUnicode(const std::string& str, atInt32 fixedLen = -1);
|
||||
void fill(atInt8 byte, atUint64 len);
|
||||
inline void fill(atUint8 byte, atUint64 len)
|
||||
{FileWriter::fill((atInt8)byte, len);}
|
||||
|
||||
private:
|
||||
std::string m_filename;
|
||||
FILE* m_fileHandle;
|
||||
Endian m_endian;
|
||||
atUint8 m_currentByte;
|
||||
atUint64 m_bytePosition;
|
||||
atUint8 m_bitShift;
|
||||
bool m_bitValid;
|
||||
};
|
||||
}
|
||||
} // Athena
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef GLOBAL_HPP
|
||||
#define GLOBAL_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include "Athena/Types.hpp"
|
||||
#include "Athena/Utility.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4996)
|
||||
|
|
|
@ -19,12 +19,10 @@ public:
|
|||
virtual Endian endian() const = 0;
|
||||
virtual bool isBigEndian() const = 0;
|
||||
virtual bool isLittleEndian()const = 0;
|
||||
virtual bool isOpen() const = 0;
|
||||
virtual void seek(atInt64, SeekOrigin) = 0;
|
||||
virtual bool atEnd() const = 0;
|
||||
virtual atUint64 position() const = 0;
|
||||
virtual atUint64 length() const = 0;
|
||||
virtual void seekBit(int) = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef ISTREAMREADER_HPP
|
||||
#define ISTREAMREADER_HPP
|
||||
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include "IStream.hpp"
|
||||
|
||||
namespace Athena
|
||||
|
@ -11,38 +13,353 @@ class IStreamReader : public IStream
|
|||
{
|
||||
public:
|
||||
virtual ~IStreamReader() {}
|
||||
virtual void setEndian(Endian) = 0;
|
||||
virtual Endian endian() const = 0;
|
||||
virtual bool isBigEndian() const = 0;
|
||||
virtual bool isLittleEndian()const = 0;
|
||||
virtual bool isOpen() const = 0;
|
||||
virtual void seek(atInt64, SeekOrigin) = 0;
|
||||
virtual void seekAlign32() = 0;
|
||||
virtual bool atEnd() const = 0;
|
||||
virtual atUint64 position() const = 0;
|
||||
virtual atUint64 length() const = 0;
|
||||
virtual void seekBit(int) = 0;
|
||||
virtual bool readBit() = 0;
|
||||
virtual atUint8 readUByte() = 0;
|
||||
virtual atInt8 readByte() = 0;
|
||||
virtual atUint8* readUBytes(atUint64) = 0;
|
||||
virtual atInt8* readBytes(atUint64) = 0;
|
||||
virtual atUint64 readUBytesToBuf(void*, atUint64) = 0;
|
||||
virtual atUint64 readBytesToBuf(void*, atUint64) = 0;
|
||||
virtual atUint16 readUint16() = 0;
|
||||
virtual atInt16 readInt16() = 0;
|
||||
virtual atUint32 readUint32() = 0;
|
||||
virtual atInt32 readInt32() = 0;
|
||||
virtual atUint64 readUint64() = 0;
|
||||
virtual atInt64 readInt64() = 0;
|
||||
virtual double readDouble() = 0;
|
||||
virtual float readFloat() = 0;
|
||||
virtual bool readBool() = 0;
|
||||
virtual atVec3f readVec3f() = 0;
|
||||
virtual atVec4f readVec4f() = 0;
|
||||
virtual std::string readUnicode(atInt32 = -1) = 0;
|
||||
virtual std::string readString(atInt32 = -1) = 0;
|
||||
virtual std::wstring readWString(atInt32 = -1) = 0;
|
||||
|
||||
/*! \brief Sets the Endianss of the stream
|
||||
*
|
||||
* \param endian The Endianess to set \sa Endian
|
||||
*/
|
||||
inline void setEndian(Endian endian)
|
||||
{m_endian = endian;}
|
||||
|
||||
/*! \brief Returns the current Endianness of the stream
|
||||
*
|
||||
* \return Endian The current Stream Endianess
|
||||
*/
|
||||
inline Endian endian() const
|
||||
{return m_endian;}
|
||||
|
||||
/*! \brief Returns whether the stream is BigEndian
|
||||
*
|
||||
* \return bool True for BigEndian; False for LittleEndian
|
||||
*/
|
||||
inline bool isBigEndian() const
|
||||
{return (m_endian == Endian::BigEndian);}
|
||||
|
||||
/*! \brief Returns whether the stream is LittleEndian
|
||||
*
|
||||
* \return bool True for LittleEndian; False for BigEndian
|
||||
*/
|
||||
inline bool isLittleEndian()const
|
||||
{return (m_endian == Endian::LittleEndian);}
|
||||
|
||||
|
||||
/*! \brief Sets the buffers position relative to the specified position.<br />
|
||||
* It seeks relative to the current position by default.
|
||||
* \param position where in the buffer to seek
|
||||
* \param origin The Origin to seek \sa SeekOrigin
|
||||
*/
|
||||
virtual void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current)=0;
|
||||
|
||||
/*! \brief Sets the buffers position relative to the next 32-byte aligned position.<br />
|
||||
*/
|
||||
inline void seekAlign32() {seek(ROUND_UP_32(position()), SeekOrigin::Begin);}
|
||||
|
||||
/*! \brief Returns whether or not the stream is at the end.
|
||||
*
|
||||
* \return bool True if at end; False otherwise.
|
||||
*/
|
||||
inline bool atEnd() const
|
||||
{return position() >= length();}
|
||||
|
||||
/*! \brief Returns the current position in the stream.
|
||||
*
|
||||
* \return Int64 The current position in the stream.
|
||||
*/
|
||||
virtual atUint64 position() const=0;
|
||||
|
||||
/*! \brief Returns whether or not the stream is at the end.
|
||||
*
|
||||
* \return bool True if at end; False otherwise.
|
||||
*/
|
||||
virtual atUint64 length() const=0;
|
||||
|
||||
/*! \brief Reads a byte at the current position and advances the current position
|
||||
*
|
||||
* \return Int8 The value at the current position
|
||||
*/
|
||||
inline atInt8 readByte() {atInt8 val; readUBytesToBuf(&val, 1); return val;}
|
||||
|
||||
/*! \brief Reads a byte at the current position and advances the current position
|
||||
*
|
||||
* \return Uint8 The value at the current position
|
||||
*/
|
||||
inline atUint8 readUByte() {return readByte();}
|
||||
|
||||
/*! \brief Reads a byte at the current position and advances the current position.
|
||||
*
|
||||
* \return Uint8* The buffer at the current position from the given length.
|
||||
*/
|
||||
inline atInt8* readBytes(atUint64 length)
|
||||
{atInt8* buf = new atInt8[length]; readUBytesToBuf(buf, length); return buf;}
|
||||
|
||||
/*! \brief Reads a byte at the current position and advances the current position.
|
||||
*
|
||||
* \return Int8* The buffer at the current position from the given length.
|
||||
*/
|
||||
inline atUint8* readUBytes(atUint64 length) {return (atUint8*)readBytes(length);}
|
||||
|
||||
inline atUint64 readBytesToBuf(void* buf, atUint64 len) {return readUBytesToBuf(buf, len);}
|
||||
virtual atUint64 readUBytesToBuf(void* buf, atUint64 len)=0;
|
||||
|
||||
/*! \brief Reads a Int16 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Int16 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atInt16 readInt16()
|
||||
{
|
||||
atInt16 val;
|
||||
readUBytesToBuf(&val, 2);
|
||||
return m_endian == BigEndian ? utility::BigInt16(val) : utility::LittleInt16(val);
|
||||
}
|
||||
|
||||
/*! \brief Reads a Uint16 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Uint16 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atUint16 readUint16()
|
||||
{return readInt16();}
|
||||
|
||||
/*! \brief Reads a Int32 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Int32 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atInt32 readInt32()
|
||||
{
|
||||
atInt32 val;
|
||||
readUBytesToBuf(&val, 4);
|
||||
return m_endian == BigEndian ? utility::BigInt32(val) : utility::LittleInt32(val);
|
||||
}
|
||||
|
||||
/*! \brief Reads a Uint32 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Uint32 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atUint32 readUint32()
|
||||
{return readInt32();}
|
||||
|
||||
/*! \brief Reads a Int64 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Int64 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atInt64 readInt64()
|
||||
{
|
||||
atInt64 val;
|
||||
readUBytesToBuf(&val, 8);
|
||||
return m_endian == BigEndian ? utility::BigInt64(val) : utility::LittleInt64(val);
|
||||
}
|
||||
|
||||
/*! \brief Reads a Uint64 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Uint64 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atUint64 readUint64()
|
||||
{return readInt64();}
|
||||
|
||||
/*! \brief Reads a float and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return float The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline float readFloat()
|
||||
{
|
||||
float val;
|
||||
readUBytesToBuf(&val, 4);
|
||||
return m_endian == BigEndian ? utility::BigFloat(val) : utility::LittleFloat(val);
|
||||
}
|
||||
|
||||
/*! \brief Reads a double and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return double The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline double readDouble()
|
||||
{
|
||||
double val;
|
||||
readUBytesToBuf(&val, 8);
|
||||
return m_endian == BigEndian ? utility::BigDouble(val) : utility::LittleDouble(val);
|
||||
}
|
||||
|
||||
/*! \brief Reads a bool and advances the current position
|
||||
*
|
||||
* \return bool The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline bool readBool()
|
||||
{
|
||||
atUint8 val;
|
||||
readUBytesToBuf(&val, 1);
|
||||
return val != 0;
|
||||
}
|
||||
|
||||
/*! \brief Reads an atVec3f (12 bytes) and advances the current position
|
||||
*
|
||||
* \return atVec3f The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atVec3f readVec3f()
|
||||
{
|
||||
atVec3f val;
|
||||
readUBytesToBuf(&val, 12);
|
||||
if (m_endian == BigEndian)
|
||||
{
|
||||
utility::BigFloat(val.vec[0]);
|
||||
utility::BigFloat(val.vec[1]);
|
||||
utility::BigFloat(val.vec[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
utility::LittleFloat(val.vec[0]);
|
||||
utility::LittleFloat(val.vec[1]);
|
||||
utility::LittleFloat(val.vec[2]);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/*! \brief Reads an atVec4f (16 bytes) and advances the current position
|
||||
*
|
||||
* \return atVec4f The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atVec4f readVec4f()
|
||||
{
|
||||
atVec4f val;
|
||||
readUBytesToBuf(&val, 16);
|
||||
if (m_endian == BigEndian)
|
||||
{
|
||||
utility::BigFloat(val.vec[0]);
|
||||
utility::BigFloat(val.vec[1]);
|
||||
utility::BigFloat(val.vec[2]);
|
||||
utility::BigFloat(val.vec[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
utility::LittleFloat(val.vec[0]);
|
||||
utility::LittleFloat(val.vec[1]);
|
||||
utility::LittleFloat(val.vec[2]);
|
||||
utility::LittleFloat(val.vec[3]);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/*! \brief Reads a Unicode string and advances the position in the file
|
||||
*
|
||||
* \param fixedLen If non-negative, this is a fixed-length string read
|
||||
* \return std::string The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline std::string readUnicode(atInt32 fixedLen = -1)
|
||||
{
|
||||
std::wstring tmp;
|
||||
atUint16 chr = readUint16();
|
||||
|
||||
atInt32 i;
|
||||
for (i = 0 ;; ++i)
|
||||
{
|
||||
if (fixedLen >= 0 && i >= fixedLen - 1)
|
||||
break;
|
||||
|
||||
if (!chr)
|
||||
break;
|
||||
|
||||
tmp.push_back(chr);
|
||||
chr = readUint16();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
return conv.to_bytes(tmp);
|
||||
}
|
||||
|
||||
/*! \brief Reads a string and advances the position in the file
|
||||
*
|
||||
* \param fixedLen If non-negative, this is a fixed-length string read
|
||||
* \return std::string The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline std::string readString(atInt32 fixedLen = -1)
|
||||
{
|
||||
std::string ret;
|
||||
atUint8 chr = readByte();
|
||||
|
||||
atInt32 i;
|
||||
for (i = 1 ; chr != 0 ; ++i)
|
||||
{
|
||||
ret += chr;
|
||||
|
||||
if (fixedLen >= 0 && i >= fixedLen)
|
||||
break;
|
||||
|
||||
chr = readByte();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*! \brief Reads a wstring and advances the position in the file
|
||||
*
|
||||
* \param fixedLen If non-negative, this is a fixed-length string read
|
||||
* \return std::wstring The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline std::wstring readWString(atInt32 fixedLen = -1)
|
||||
{
|
||||
std::wstring ret;
|
||||
atUint16 chr = readUint16();
|
||||
|
||||
atInt32 i;
|
||||
for (i = 1 ; chr != 0 ; ++i)
|
||||
{
|
||||
ret += chr;
|
||||
|
||||
if (fixedLen >= 0 && i >= fixedLen)
|
||||
break;
|
||||
|
||||
chr = readUint16();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected:
|
||||
Endian m_endian;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef ISTREAMWRITER_HPP
|
||||
#define ISTREAMWRITER_HPP
|
||||
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include "IStream.hpp"
|
||||
|
||||
namespace Athena
|
||||
|
@ -11,38 +13,365 @@ class IStreamWriter : public IStream
|
|||
{
|
||||
public:
|
||||
virtual ~IStreamWriter() {}
|
||||
virtual void setEndian(Endian) = 0;
|
||||
virtual Endian endian() const = 0;
|
||||
virtual bool isBigEndian() const = 0;
|
||||
virtual bool isLittleEndian()const = 0;
|
||||
virtual bool isOpen() const = 0;
|
||||
virtual void seek(atInt64, SeekOrigin) = 0;
|
||||
virtual void seekAlign32() = 0;
|
||||
virtual bool atEnd() const = 0;
|
||||
virtual atUint64 position() const = 0;
|
||||
virtual atUint64 length() const = 0;
|
||||
virtual void seekBit(int) = 0;
|
||||
virtual void writeBit(bool) = 0;
|
||||
virtual void writeUByte(atUint8) = 0;
|
||||
virtual void writeByte(atInt8) = 0;
|
||||
virtual void writeUBytes(const atUint8*, atUint64) = 0;
|
||||
virtual void writeBytes(const atInt8*, atUint64) = 0;
|
||||
virtual void writeUint16(atUint16) = 0;
|
||||
virtual void writeInt16(atInt16) = 0;
|
||||
virtual void writeUint32(atUint32) = 0;
|
||||
virtual void writeInt32(atInt32) = 0;
|
||||
virtual void writeUint64(atUint64) = 0;
|
||||
virtual void writeInt64(atInt64) = 0;
|
||||
virtual void writeDouble(double) = 0;
|
||||
virtual void writeFloat(float) = 0;
|
||||
virtual void writeBool(bool) = 0;
|
||||
virtual void writeVec3f(atVec3f vec) = 0;
|
||||
virtual void writeVec4f(atVec4f vec) = 0;
|
||||
virtual void writeString(const std::string&, atInt32 = -1) = 0;
|
||||
virtual void writeWString(const std::wstring&, atInt32 = -1) = 0;
|
||||
virtual void writeUnicode(const std::string&, atInt32 = -1) = 0;
|
||||
virtual void fill(atUint8, atUint64) = 0;
|
||||
virtual void fill(atInt8, atUint64) = 0;
|
||||
/*! \brief Sets the Endianss of the stream
|
||||
*
|
||||
* \param endian The Endianess to set \sa Endian
|
||||
*/
|
||||
inline void setEndian(Endian endian)
|
||||
{m_endian = endian;}
|
||||
|
||||
/*! \brief Returns the current Endianness of the stream
|
||||
*
|
||||
* \return Endian The current Stream Endianess
|
||||
*/
|
||||
inline Endian endian() const
|
||||
{return m_endian;}
|
||||
|
||||
/*! \brief Returns whether the stream is BigEndian
|
||||
*
|
||||
* \return bool True for BigEndian; False for LittleEndian
|
||||
*/
|
||||
inline bool isBigEndian() const
|
||||
{return (m_endian == Endian::BigEndian);}
|
||||
|
||||
/*! \brief Returns whether the stream is LittleEndian
|
||||
*
|
||||
* \return bool True for LittleEndian; False for BigEndian
|
||||
*/
|
||||
inline bool isLittleEndian() const
|
||||
{return (m_endian == Endian::LittleEndian);}
|
||||
|
||||
/*! \brief Sets the buffers position relative to the specified position.<br />
|
||||
* It seeks relative to the current position by default.
|
||||
* \param position where in the buffer to seek
|
||||
* \param origin The Origin to seek \sa SeekOrigin
|
||||
*/
|
||||
virtual void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current)=0;
|
||||
|
||||
/*! \brief Sets the buffers position relative to the next 32-byte aligned position.<br />
|
||||
*/
|
||||
inline void seekAlign32() {seek(ROUND_UP_32(position()), SeekOrigin::Begin);}
|
||||
|
||||
/*! \brief Returns whether or not the stream is at the end.
|
||||
*
|
||||
* \return bool True if at end; False otherwise.
|
||||
*/
|
||||
inline bool atEnd() const {return position() >= length();}
|
||||
|
||||
/*! \brief Returns the current position in the stream.
|
||||
*
|
||||
* \return Int64 The current position in the stream.
|
||||
*/
|
||||
virtual atUint64 position() const=0;
|
||||
|
||||
/*! \brief Returns whether or not the stream is at the end.
|
||||
*
|
||||
* \return bool True if at end; False otherwise.
|
||||
*/
|
||||
virtual atUint64 length() const=0;
|
||||
|
||||
/*! \brief Writes a byte at the current position and advances the position by one byte.
|
||||
* \param byte The value to write
|
||||
*/
|
||||
inline void writeUByte(atUint8 val) {writeUBytes(&val, 1);}
|
||||
|
||||
/*! \brief Writes a byte at the current position and advances the position by one byte.
|
||||
* \param byte The value to write
|
||||
* \throw IOException
|
||||
*/
|
||||
inline void writeByte(atInt8 val) {writeUByte(val);}
|
||||
|
||||
/*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length
|
||||
* however it's undefined behavior to try and write a buffer which is smaller than the given length.
|
||||
*
|
||||
* \param data The buffer to write
|
||||
* \param length The amount to write
|
||||
*/
|
||||
virtual void writeUBytes(const atUint8* data, atUint64 len)=0;
|
||||
|
||||
/*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length
|
||||
* however it's undefined behavior to try and write a buffer which is smaller than the given length.
|
||||
*
|
||||
* \param data The buffer to write
|
||||
* \param length The amount to write
|
||||
*/
|
||||
inline void writeBytes(const atInt8* data, atUint64 len) {writeUBytes((atUint8*)data, len);}
|
||||
|
||||
/*! \brief Writes an Int16 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeInt16(atInt16 val)
|
||||
{
|
||||
if (m_endian == BigEndian)
|
||||
utility::BigInt16(val);
|
||||
else
|
||||
utility::LittleInt16(val);
|
||||
writeUBytes((atUint8*)&val, 2);
|
||||
}
|
||||
|
||||
/*! \brief Writes an Uint16 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeUint16(atUint16 val) {writeInt16(val);}
|
||||
|
||||
/*! \brief Writes an Int32 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeInt32(atInt32 val)
|
||||
{
|
||||
if (m_endian == BigEndian)
|
||||
utility::BigInt32(val);
|
||||
else
|
||||
utility::LittleInt32(val);
|
||||
writeUBytes((atUint8*)&val, 4);
|
||||
}
|
||||
|
||||
/*! \brief Writes an Uint32 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeUint32(atUint32 val) {writeInt32(val);}
|
||||
|
||||
/*! \brief Writes an Int64 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeInt64(atInt64 val)
|
||||
{
|
||||
if (m_endian == BigEndian)
|
||||
utility::BigInt64(val);
|
||||
else
|
||||
utility::LittleInt64(val);
|
||||
writeUBytes((atUint8*)&val, 8);
|
||||
}
|
||||
|
||||
/*! \brief Writes an Uint64 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeUint64(atUint64 val) {writeInt64(val);}
|
||||
|
||||
/*! \brief Writes an float to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeFloat(float val)
|
||||
{
|
||||
if (m_endian == BigEndian)
|
||||
utility::BigFloat(val);
|
||||
else
|
||||
utility::LittleFloat(val);
|
||||
writeUBytes((atUint8*)&val, 4);
|
||||
}
|
||||
|
||||
/*! \brief Writes an double to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeDouble(double val)
|
||||
{
|
||||
if (m_endian == BigEndian)
|
||||
utility::BigDouble(val);
|
||||
else
|
||||
utility::LittleDouble(val);
|
||||
writeUBytes((atUint8*)&val, 8);
|
||||
}
|
||||
|
||||
/*! \brief Writes an bool to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeBool(bool val) {writeUBytes((atUint8*)&val, 1);}
|
||||
|
||||
/*! \brief Writes an atVec3f (12 bytes) to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param vec The value to write to the buffer
|
||||
*/
|
||||
inline void writeVec3f(atVec3f vec)
|
||||
{
|
||||
if (m_endian == BigEndian)
|
||||
{
|
||||
utility::BigFloat(vec.vec[0]);
|
||||
utility::BigFloat(vec.vec[1]);
|
||||
utility::BigFloat(vec.vec[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
utility::LittleFloat(vec.vec[0]);
|
||||
utility::LittleFloat(vec.vec[1]);
|
||||
utility::LittleFloat(vec.vec[2]);
|
||||
}
|
||||
writeUBytes((atUint8*)&vec, 12);
|
||||
}
|
||||
|
||||
/*! \brief Writes an atVec4f (16 bytes) to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param vec The value to write to the buffer
|
||||
*/
|
||||
inline void writeVec4f(atVec4f vec)
|
||||
{
|
||||
if (m_endian == BigEndian)
|
||||
{
|
||||
utility::BigFloat(vec.vec[0]);
|
||||
utility::BigFloat(vec.vec[1]);
|
||||
utility::BigFloat(vec.vec[2]);
|
||||
utility::BigFloat(vec.vec[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
utility::LittleFloat(vec.vec[0]);
|
||||
utility::LittleFloat(vec.vec[1]);
|
||||
utility::LittleFloat(vec.vec[2]);
|
||||
utility::LittleFloat(vec.vec[3]);
|
||||
}
|
||||
writeUBytes((atUint8*)&vec, 16);
|
||||
}
|
||||
|
||||
/*! \brief Writes an unicode string to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param str The string to write to the buffer
|
||||
* \param fixedLen If not -1, the number of characters to zero-fill string to
|
||||
*/
|
||||
inline void writeUnicode(const std::string& str, atInt32 fixedLen = -1)
|
||||
{
|
||||
std::string tmpStr = "\xEF\xBB\xBF" + str;
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
std::wstring tmp = conv.from_bytes(tmpStr);
|
||||
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
for (atUint16 chr : tmp)
|
||||
{
|
||||
if (chr != 0xFEFF)
|
||||
writeUint16(chr);
|
||||
}
|
||||
writeUint16(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = tmp.begin();
|
||||
for (atInt32 i=0 ; i<fixedLen ; ++i)
|
||||
{
|
||||
atUint16 chr;
|
||||
if (it == tmp.end())
|
||||
chr = 0;
|
||||
else
|
||||
chr = *it++;
|
||||
|
||||
if (chr == 0xFEFF)
|
||||
{
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
writeUint16(chr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Writes an string to the buffer and advances the buffer.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param str The string to write to the buffer
|
||||
* \param fixedLen If not -1, the number of characters to zero-fill string to
|
||||
*/
|
||||
inline void writeString(const std::string& str, atInt32 fixedLen = -1)
|
||||
{
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
for (atUint8 c : str)
|
||||
{
|
||||
writeUByte(c);
|
||||
|
||||
if (c == '\0')
|
||||
break;
|
||||
}
|
||||
writeUByte(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = str.begin();
|
||||
for (atInt32 i=0 ; i<fixedLen ; ++i)
|
||||
{
|
||||
atUint8 chr;
|
||||
if (it == str.end())
|
||||
chr = 0;
|
||||
else
|
||||
chr = *it++;
|
||||
writeUByte(chr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Writes an wstring to the buffer and advances the buffer.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param str The string to write to the buffer
|
||||
* \param fixedLen If not -1, the number of characters to zero-fill string to
|
||||
*/
|
||||
inline void writeWString(const std::wstring& str, atInt32 fixedLen = -1)
|
||||
{
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
for (atUint16 c : str)
|
||||
{
|
||||
writeUint16(c);
|
||||
|
||||
if (c == L'\0')
|
||||
break;
|
||||
}
|
||||
writeUint16(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = str.begin();
|
||||
for (atInt32 i=0 ; i<fixedLen ; ++i)
|
||||
{
|
||||
atUint16 chr;
|
||||
if (it == str.end())
|
||||
chr = 0;
|
||||
else
|
||||
chr = *it++;
|
||||
writeUint16(chr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void fill(atUint8 val, atUint64 length)
|
||||
{for (atUint64 l=0 ; l<length ; ++l) writeUBytes(&val, 1);}
|
||||
inline void fill(atInt8 val, atUint64 length)
|
||||
{fill((atUint8)val, length);}
|
||||
|
||||
protected:
|
||||
Endian m_endian;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ namespace Athena
|
|||
{
|
||||
namespace io
|
||||
{
|
||||
/*! \class BinaryReader
|
||||
* \brief A Stream class for reading binary data
|
||||
/*! \class MemoryReader
|
||||
* \brief A Stream class for reading data from a memory position
|
||||
*
|
||||
* A Class for reading binary data from a file or memory stream,
|
||||
* all work is done using a memory buffer, and not read directly from the disk
|
||||
|
@ -20,6 +20,8 @@ namespace io
|
|||
class MemoryReader : public IStreamReader
|
||||
{
|
||||
public:
|
||||
~MemoryReader();
|
||||
|
||||
/*! \brief This constructor takes an existing buffer to read from.
|
||||
*
|
||||
* \param data The existing buffer
|
||||
|
@ -31,45 +33,7 @@ public:
|
|||
*
|
||||
* \param filename The file to create the stream from
|
||||
*/
|
||||
MemoryReader(const std::string& filename, std::function<void(int)> progressFun = nullptr);
|
||||
|
||||
virtual ~MemoryReader();
|
||||
|
||||
/*! \brief Sets the Endianss of the stream
|
||||
*
|
||||
* \param endian The Endianess to set \sa Endian
|
||||
*/
|
||||
inline void setEndian(Endian endian)
|
||||
{m_endian = endian;}
|
||||
|
||||
/*! \brief Returns the current Endianness of the stream
|
||||
*
|
||||
* \return Endian The current Stream Endianess
|
||||
*/
|
||||
inline Endian endian() const
|
||||
{return m_endian;}
|
||||
|
||||
/*! \brief Returns whether the stream is BigEndian
|
||||
*
|
||||
* \return bool True for BigEndian; False for LittleEndian
|
||||
*/
|
||||
inline bool isBigEndian() const
|
||||
{return (m_endian == Endian::BigEndian);}
|
||||
|
||||
/*! \brief Returns whether the stream is LittleEndian
|
||||
*
|
||||
* \return bool True for LittleEndian; False for BigEndian
|
||||
*/
|
||||
inline bool isLittleEndian()const
|
||||
{return (m_endian == Endian::LittleEndian);}
|
||||
|
||||
/*! \brief Retuns whether or not the Stream is open.
|
||||
*
|
||||
* \return True if open; False otherwise.
|
||||
*/
|
||||
inline bool isOpen() const
|
||||
{return m_data != nullptr;}
|
||||
|
||||
MemoryReader(const std::string& filename);
|
||||
|
||||
/*! \brief Sets the buffers position relative to the specified position.<br />
|
||||
* It seeks relative to the current position by default.
|
||||
|
@ -78,17 +42,6 @@ public:
|
|||
*/
|
||||
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
|
||||
|
||||
/*! \brief Sets the buffers position relative to the next 32-byte aligned position.<br />
|
||||
*/
|
||||
inline void seekAlign32() {seek(ROUND_UP_32(m_position), SeekOrigin::Begin);}
|
||||
|
||||
/*! \brief Returns whether or not the stream is at the end.
|
||||
*
|
||||
* \return bool True if at end; False otherwise.
|
||||
*/
|
||||
inline bool atEnd() const
|
||||
{return m_position >= m_length;}
|
||||
|
||||
/*! \brief Returns the current position in the stream.
|
||||
*
|
||||
* \return Int64 The current position in the stream.
|
||||
|
@ -113,7 +66,7 @@ public:
|
|||
* \param length The length of the new buffer.
|
||||
* \throw IOException
|
||||
*/
|
||||
void setData(const atUint8* data, atUint64 length);
|
||||
void setData(const atUint8* data, atUint64 length);
|
||||
|
||||
|
||||
/*! \brief Returns a copy of the current buffer.<br />
|
||||
|
@ -125,199 +78,14 @@ public:
|
|||
*/
|
||||
atUint8* data() const;
|
||||
|
||||
/*! \brief Sets the target file
|
||||
*
|
||||
* \sa Endian
|
||||
* \param filepath The path to write to.
|
||||
*/
|
||||
inline void setFilepath(const std::string& filepath)
|
||||
{m_filepath = filepath;}
|
||||
|
||||
/*! \brief Returns the target file
|
||||
*
|
||||
*/
|
||||
inline std::string filepath() const
|
||||
{return m_filepath;}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Seeks to the specified bit within the current byte
|
||||
* \param bit Bit to seek to, range is 0 - 7
|
||||
*/
|
||||
void seekBit(int bit);
|
||||
|
||||
/*! \brief Reads a bit at the current position and advances the current position
|
||||
*
|
||||
* \return bool The value at the current position
|
||||
*/
|
||||
bool readBit();
|
||||
|
||||
/*! \brief Reads a byte at the current position and advances the current position
|
||||
*
|
||||
* \return Int8 The value at the current position
|
||||
*/
|
||||
atInt8 readByte();
|
||||
|
||||
/*! \brief Reads a byte at the current position and advances the current position
|
||||
*
|
||||
* \return Uint8 The value at the current position
|
||||
*/
|
||||
atUint8 readUByte();
|
||||
|
||||
/*! \brief Reads a byte at the current position and advances the current position.
|
||||
*
|
||||
* \return Uint8* The buffer at the current position from the given length.
|
||||
*/
|
||||
inline atInt8* readBytes(atUint64 length) {return (atInt8*)readUBytes(length);}
|
||||
|
||||
/*! \brief Reads a byte at the current position and advances the current position.
|
||||
*
|
||||
* \return Int8* The buffer at the current position from the given length.
|
||||
*/
|
||||
atUint8* readUBytes(atUint64 length);
|
||||
|
||||
atUint64 readBytesToBuf(void* buf, atUint64 len) {return readUBytesToBuf(buf, len);}
|
||||
atUint64 readUBytesToBuf(void* buf, atUint64 len);
|
||||
|
||||
/*! \brief Reads a Int16 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Int16 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
atInt16 readInt16();
|
||||
|
||||
/*! \brief Reads a Uint16 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Uint16 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atUint16 readUint16()
|
||||
{return MemoryReader::readInt16();}
|
||||
|
||||
/*! \brief Reads a Int32 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Int32 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
atInt32 readInt32();
|
||||
|
||||
/*! \brief Reads a Uint32 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Uint32 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atUint32 readUint32()
|
||||
{return MemoryReader::readInt32();}
|
||||
|
||||
/*! \brief Reads a Int64 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Int64 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
atInt64 readInt64();
|
||||
|
||||
/*! \brief Reads a Uint64 and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return Uint64 The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
inline atUint64 readUint64()
|
||||
{return MemoryReader::readInt64();}
|
||||
|
||||
/*! \brief Reads a float and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return float The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
float readFloat();
|
||||
|
||||
/*! \brief Reads a double and swaps to proper endianness depending on platform
|
||||
* and Stream settings, and advances the current position
|
||||
*
|
||||
* \sa Endian
|
||||
*
|
||||
* \return double The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
double readDouble();
|
||||
|
||||
/*! \brief Reads a bool and advances the current position
|
||||
*
|
||||
* \return bool The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
bool readBool();
|
||||
|
||||
/*! \brief Reads an atVec3f (12 bytes) and advances the current position
|
||||
*
|
||||
* \return atVec3f The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
atVec3f readVec3f();
|
||||
|
||||
/*! \brief Reads an atVec4f (16 bytes) and advances the current position
|
||||
*
|
||||
* \return atVec4f The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
atVec4f readVec4f();
|
||||
|
||||
/*! \brief Reads a Unicode string and advances the position in the file
|
||||
*
|
||||
* \param fixedLen If non-negative, this is a fixed-length string read
|
||||
* \return std::string The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
std::string readUnicode(atInt32 fixedLen = -1);
|
||||
|
||||
/*! \brief Reads a string and advances the position in the file
|
||||
*
|
||||
* \param fixedLen If non-negative, this is a fixed-length string read
|
||||
* \return std::string The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
std::string readString(atInt32 fixedLen = -1);
|
||||
|
||||
/*! \brief Reads a wstring and advances the position in the file
|
||||
*
|
||||
* \param fixedLen If non-negative, this is a fixed-length string read
|
||||
* \return std::wstring The value at the current address
|
||||
* \throw IOException when address is out of range
|
||||
*/
|
||||
std::wstring readWString(atInt32 fixedLen = -1);
|
||||
|
||||
inline void setProgressCallback(std::function<void(int)> cb)
|
||||
{m_progressCallback = cb;}
|
||||
protected:
|
||||
void loadData();
|
||||
atUint8* m_data;
|
||||
atUint64 m_length;
|
||||
std::string m_filepath; //!< Path to the target file
|
||||
std::string m_filepath; //!< Path to the target file
|
||||
atUint64 m_position;
|
||||
atUint64 m_bitPosition;
|
||||
Endian m_endian;
|
||||
std::function<void(int)> m_progressCallback;
|
||||
};
|
||||
|
||||
} // io
|
||||
|
|
|
@ -10,8 +10,8 @@ namespace Athena
|
|||
namespace io
|
||||
{
|
||||
|
||||
/*! \class BinaryWriter
|
||||
* \brief A Stream class for writing binary data
|
||||
/*! \class MemoryWriter
|
||||
* \brief A Stream class for writing data to a memory position
|
||||
*
|
||||
* A Class for writing binary data to a file or memory stream,
|
||||
* all work is done using a memory buffer, and not written directly to the disk
|
||||
|
@ -21,6 +21,8 @@ namespace io
|
|||
class MemoryWriter : public IStreamWriter
|
||||
{
|
||||
public:
|
||||
~MemoryWriter();
|
||||
|
||||
/*! \brief This constructor takes an existing buffer to write to.
|
||||
*
|
||||
* \param data The existing buffer
|
||||
|
@ -34,43 +36,6 @@ public:
|
|||
*/
|
||||
MemoryWriter(const std::string& filename, std::function<void(int)> progressFun = nullptr);
|
||||
|
||||
virtual ~MemoryWriter();
|
||||
|
||||
/*! \brief Sets the Endianss of the stream
|
||||
*
|
||||
* \param endian The Endianess to set \sa Endian
|
||||
*/
|
||||
inline void setEndian(Endian endian)
|
||||
{m_endian = endian;}
|
||||
|
||||
/*! \brief Returns the current Endianness of the stream
|
||||
*
|
||||
* \return Endian The current Stream Endianess
|
||||
*/
|
||||
inline Endian endian() const
|
||||
{return m_endian;}
|
||||
|
||||
/*! \brief Returns whether the stream is BigEndian
|
||||
*
|
||||
* \return bool True for BigEndian; False for LittleEndian
|
||||
*/
|
||||
inline bool isBigEndian() const
|
||||
{return (m_endian == Endian::BigEndian);}
|
||||
|
||||
/*! \brief Returns whether the stream is LittleEndian
|
||||
*
|
||||
* \return bool True for LittleEndian; False for BigEndian
|
||||
*/
|
||||
inline bool isLittleEndian() const
|
||||
{return (m_endian == Endian::LittleEndian);}
|
||||
|
||||
/*! \brief Retuns whether or not the Stream is open.
|
||||
*
|
||||
* \return True if open; False otherwise.
|
||||
*/
|
||||
inline bool isOpen() const
|
||||
{return m_data != nullptr;}
|
||||
|
||||
|
||||
/*! \brief Sets the buffers position relative to the specified position.<br />
|
||||
* It seeks relative to the current position by default.
|
||||
|
@ -79,18 +44,6 @@ public:
|
|||
*/
|
||||
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
|
||||
|
||||
/*! \brief Sets the buffers position relative to the next 32-byte aligned position.<br />
|
||||
*/
|
||||
inline void seekAlign32() {seek(ROUND_UP_32(m_position), SeekOrigin::Begin);}
|
||||
|
||||
|
||||
/*! \brief Returns whether or not the stream is at the end.
|
||||
*
|
||||
* \return bool True if at end; False otherwise.
|
||||
*/
|
||||
inline bool atEnd() const
|
||||
{return m_position >= m_length;}
|
||||
|
||||
|
||||
/*! \brief Returns the current position in the stream.
|
||||
*
|
||||
|
@ -106,6 +59,8 @@ public:
|
|||
inline atUint64 length() const
|
||||
{return m_length;}
|
||||
|
||||
inline bool isOpen() const {return true;}
|
||||
|
||||
/*! \brief Sets the buffer to the given one, deleting the current one.<br />
|
||||
* <b>BEWARE:</b> As this deletes the current buffer it WILL cause a loss of data
|
||||
* if that was not the intent.<br />
|
||||
|
@ -147,30 +102,6 @@ public:
|
|||
*/
|
||||
void save(const std::string& filename = "");
|
||||
|
||||
/*!
|
||||
* \brief Seeks to the specified bit within the current byte
|
||||
* \param bit Bit to seek to, range is 0 - 7
|
||||
*/
|
||||
void seekBit(int bit);
|
||||
|
||||
/*! \brief Writes a bit at the current position and advances the position by one bit.
|
||||
* \param val the value to write
|
||||
* \throw IOException
|
||||
*/
|
||||
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
|
||||
*/
|
||||
void writeUByte(atUint8 val);
|
||||
|
||||
/*! \brief Writes a byte at the current position and advances the position by one byte.
|
||||
* \param byte The value to write
|
||||
* \throw IOException
|
||||
*/
|
||||
inline void writeByte(atInt8 val)
|
||||
{MemoryWriter::writeUByte(val);}
|
||||
|
||||
/*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length
|
||||
* however it's undefined behavior to try and write a buffer which is smaller than the given length.
|
||||
*
|
||||
|
@ -179,147 +110,11 @@ public:
|
|||
*/
|
||||
void writeUBytes(const atUint8* data, atUint64 len);
|
||||
|
||||
/*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length
|
||||
* however it's undefined behavior to try and write a buffer which is smaller than the given length.
|
||||
*
|
||||
* \param data The buffer to write
|
||||
* \param length The amount to write
|
||||
*/
|
||||
inline void writeBytes(const atInt8* data, atUint64 len)
|
||||
{MemoryWriter::writeUBytes((atUint8*)data, len);}
|
||||
|
||||
/*! \brief Writes an Int16 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
void writeInt16(atInt16 val);
|
||||
|
||||
/*! \brief Writes an Uint16 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeUint16(atUint16 val)
|
||||
{MemoryWriter::writeInt16(val);}
|
||||
|
||||
/*! \brief Writes an Int32 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
void writeInt32(atInt32);
|
||||
|
||||
/*! \brief Writes an Uint32 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
void writeUint32(atUint32 val)
|
||||
{MemoryWriter::writeInt32(val);}
|
||||
|
||||
/*! \brief Writes an Int64 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
void writeInt64(atInt64);
|
||||
|
||||
/*! \brief Writes an Uint64 to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
inline void writeUint64(atUint64 val)
|
||||
{MemoryWriter::writeInt64(val);}
|
||||
|
||||
/*! \brief Writes an float to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
void writeFloat(float);
|
||||
|
||||
/*! \brief Writes an double to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
void writeDouble(double);
|
||||
|
||||
/*! \brief Writes an bool to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param val The value to write to the buffer
|
||||
*/
|
||||
void writeBool(bool);
|
||||
|
||||
/*! \brief Writes an atVec3f (12 bytes) to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param vec The value to write to the buffer
|
||||
*/
|
||||
void writeVec3f(atVec3f vec);
|
||||
|
||||
/*! \brief Writes an atVec4f (16 bytes) to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param vec The value to write to the buffer
|
||||
*/
|
||||
void writeVec4f(atVec4f vec);
|
||||
|
||||
/*! \brief Writes an unicode string to the buffer and advances the buffer.
|
||||
* It also swaps the bytes depending on the platform and Stream settings.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param str The string to write to the buffer
|
||||
* \param fixedLen If not -1, the number of characters to zero-fill string to
|
||||
*/
|
||||
void writeUnicode(const std::string& str, atInt32 fixedLen = -1);
|
||||
|
||||
/*! \brief Writes an string to the buffer and advances the buffer.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param str The string to write to the buffer
|
||||
* \param fixedLen If not -1, the number of characters to zero-fill string to
|
||||
*/
|
||||
void writeString(const std::string& str, atInt32 fixedLen = -1);
|
||||
|
||||
/*! \brief Writes an wstring to the buffer and advances the buffer.
|
||||
*
|
||||
* \sa Endian
|
||||
* \param str The string to write to the buffer
|
||||
* \param fixedLen If not -1, the number of characters to zero-fill string to
|
||||
*/
|
||||
void writeWString(const std::wstring& str, atInt32 fixedLen = -1);
|
||||
|
||||
|
||||
void fill(atUint8 val, atUint64 length);
|
||||
inline void fill(atInt8 val, atUint64 length)
|
||||
{MemoryWriter::fill((atUint8)val, length);}
|
||||
|
||||
inline void setProgressCallback(std::function<void(int)> cb)
|
||||
{m_progressCallback = cb;}
|
||||
protected:
|
||||
void loadData();
|
||||
atUint8* m_data;
|
||||
atUint64 m_length;
|
||||
std::string m_filepath; //!< Path to the target file
|
||||
std::string m_filepath; //!< Path to the target file
|
||||
atUint64 m_position;
|
||||
atUint64 m_bitPosition;
|
||||
Endian m_endian;
|
||||
std::function<void(int)> m_progressCallback;
|
||||
private:
|
||||
void resize(atUint64 newSize);
|
||||
};
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef __AES_H_
|
||||
#define __AES_H_
|
||||
|
||||
#include "Athena/Types.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void aes_encrypt(atUint8* iv, const atUint8* inbuf, atUint8* outbuf, atUint64 len);
|
||||
void aes_decrypt(atUint8* iv, const atUint8* inbuf, atUint8* outbuf, atUint64 len);
|
||||
void aes_set_key(const atUint8* key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__AES_H_
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef __AES_HPP__
|
||||
#define __AES_HPP__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory>
|
||||
|
||||
namespace Athena
|
||||
{
|
||||
|
||||
class IAES
|
||||
{
|
||||
public:
|
||||
virtual void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)=0;
|
||||
virtual void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)=0;
|
||||
virtual void setKey(const uint8_t* key)=0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IAES> NewAES();
|
||||
|
||||
}
|
||||
|
||||
#endif //__AES_HPP__
|
|
@ -83,10 +83,11 @@ ALTTPFile* ALTTPFileReader::readFile()
|
|||
quest->setArrowUpgrades(base::readByte());
|
||||
quest->setHealthFiller(base::readByte());
|
||||
quest->setMagicFiller(base::readByte());
|
||||
atUint8 pendantsByte = base::readUByte();
|
||||
ALTTPPendants pendants;
|
||||
pendants.Courage = base::readBit();
|
||||
pendants.Wisdom = base::readBit();
|
||||
pendants.Power = base::readBit();
|
||||
pendants.Courage = pendantsByte & 1;
|
||||
pendants.Wisdom = (pendantsByte >> 1) & 1;
|
||||
pendants.Power = (pendantsByte >> 2) & 1;
|
||||
pendants.Unused1 = false;
|
||||
pendants.Unused2 = false;
|
||||
pendants.Unused3 = false;
|
||||
|
@ -97,15 +98,16 @@ ALTTPFile* ALTTPFileReader::readFile()
|
|||
quest->setArrowFiller(base::readByte());
|
||||
quest->setArrows(base::readByte());
|
||||
base::seek(1);
|
||||
atUint8 abilitiesByte = base::readUByte();
|
||||
ALTTPAbilities abilities;
|
||||
abilities.Nothing = base::readBit();
|
||||
abilities.Swim = base::readBit();
|
||||
abilities.Dash = base::readBit();
|
||||
abilities.Pull = base::readBit();
|
||||
abilities.Unknown1 = base::readBit();
|
||||
abilities.Talk = base::readBit();
|
||||
abilities.Read = base::readBit();
|
||||
abilities.Unknown2 = base::readBit();
|
||||
abilities.Nothing = abilitiesByte & 1;
|
||||
abilities.Swim = (abilitiesByte >> 1) & 1;
|
||||
abilities.Dash = (abilitiesByte >> 2) & 1;
|
||||
abilities.Pull = (abilitiesByte >> 3) & 1;
|
||||
abilities.Unknown1 = (abilitiesByte >> 4) & 1;
|
||||
abilities.Talk = (abilitiesByte >> 5) & 1;
|
||||
abilities.Read = (abilitiesByte >> 6) & 1;
|
||||
abilities.Unknown2 = (abilitiesByte >> 7) & 1;
|
||||
quest->setAbilityFlags(abilities);
|
||||
quest->setCrystals((ALTTPCrystals&)*base::readBytes(sizeof(ALTTPCrystals)));
|
||||
quest->setMagicUsage((ALTTPMagicUsage&)*base::readBytes(sizeof(ALTTPMagicUsage)));
|
||||
|
@ -186,22 +188,24 @@ ALTTPFile* ALTTPFileReader::readFile()
|
|||
ALTTPRoomFlags* ALTTPFileReader::readRoomFlags()
|
||||
{
|
||||
ALTTPRoomFlags* flags = new ALTTPRoomFlags;
|
||||
flags->Chest1 = base::readBit();
|
||||
flags->Chest2 = base::readBit();
|
||||
flags->Chest3 = base::readBit();
|
||||
flags->Chest4 = base::readBit();
|
||||
flags->Quadrant1 = base::readBit();
|
||||
flags->Quadrant2 = base::readBit();
|
||||
flags->Quadrant3 = base::readBit();
|
||||
flags->Quadrant4 = base::readBit();
|
||||
flags->Door1 = base::readBit();
|
||||
flags->Door2 = base::readBit();
|
||||
flags->Door3 = base::readBit();
|
||||
flags->Door4 = base::readBit();
|
||||
flags->BossBattleWon = base::readBit();
|
||||
flags->Key = base::readBit();
|
||||
flags->KeyOrChest = base::readBit();
|
||||
flags->ChestOrTile = base::readBit();
|
||||
atUint8 flagsByte = base::readUByte();
|
||||
flags->Chest1 = flagsByte & 1;
|
||||
flags->Chest2 = (flagsByte >> 1) & 1;
|
||||
flags->Chest3 = (flagsByte >> 2) & 1;
|
||||
flags->Chest4 = (flagsByte >> 3) & 1;
|
||||
flags->Quadrant1 = (flagsByte >> 4) & 1;
|
||||
flags->Quadrant2 = (flagsByte >> 5) & 1;
|
||||
flags->Quadrant3 = (flagsByte >> 6) & 1;
|
||||
flags->Quadrant4 = (flagsByte >> 7) & 1;
|
||||
flagsByte = base::readUByte();
|
||||
flags->Door1 = flagsByte & 1;
|
||||
flags->Door2 = (flagsByte >> 1) & 1;
|
||||
flags->Door3 = (flagsByte >> 2) & 1;
|
||||
flags->Door4 = (flagsByte >> 3) & 1;
|
||||
flags->BossBattleWon = (flagsByte >> 4) & 1;
|
||||
flags->Key = (flagsByte >> 5) & 1;
|
||||
flags->KeyOrChest = (flagsByte >> 6) & 1;
|
||||
flags->ChestOrTile = (flagsByte >> 7) & 1;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
@ -209,36 +213,39 @@ ALTTPRoomFlags* ALTTPFileReader::readRoomFlags()
|
|||
ALTTPOverworldEvent* ALTTPFileReader::readOverworldEvent()
|
||||
{
|
||||
ALTTPOverworldEvent* event = new ALTTPOverworldEvent;
|
||||
event->Unused1 = base::readBit();
|
||||
event->HeartPiece = base::readBit();
|
||||
event->Overlay = base::readBit();
|
||||
event->Unused2 = base::readBit();
|
||||
event->Unused3 = base::readBit();
|
||||
event->Unused4 = base::readBit();
|
||||
event->Set = base::readBit();
|
||||
event->Unused5 = base::readBit();
|
||||
atUint8 flagsByte = base::readUByte();
|
||||
event->Unused1 = flagsByte & 1;
|
||||
event->HeartPiece = (flagsByte >> 1) & 1;
|
||||
event->Overlay = (flagsByte >> 2) & 1;
|
||||
event->Unused2 = (flagsByte >> 3) & 1;
|
||||
event->Unused3 = (flagsByte >> 4) & 1;
|
||||
event->Unused4 = (flagsByte >> 5) & 1;
|
||||
event->Set = (flagsByte >> 6) & 1;
|
||||
event->Unused5 = (flagsByte >> 7) & 1;
|
||||
return event;
|
||||
}
|
||||
|
||||
ALTTPDungeonItemFlags ALTTPFileReader::readDungeonFlags()
|
||||
{
|
||||
ALTTPDungeonItemFlags flags;
|
||||
flags.Unused1 = base::readBit();
|
||||
flags.Unused2 = base::readBit();
|
||||
flags.GanonsTower = base::readBit();
|
||||
flags.TurtleRock = base::readBit();
|
||||
flags.GargoylesDomain = base::readBit();
|
||||
flags.TowerOfHera = base::readBit();
|
||||
flags.IcePalace = base::readBit();
|
||||
flags.SkullWoods = base::readBit();
|
||||
flags.MiseryMire = base::readBit();
|
||||
flags.DarkPalace = base::readBit();
|
||||
flags.SwampPalace = base::readBit();
|
||||
flags.HyruleCastle2 = base::readBit();
|
||||
flags.DesertPalace = base::readBit();
|
||||
flags.EasternPalace = base::readBit();
|
||||
flags.HyruleCastle = base::readBit();
|
||||
flags.SewerPassage = base::readBit();
|
||||
atUint8 flagsByte = base::readUByte();
|
||||
flags.Unused1 = flagsByte & 1;
|
||||
flags.Unused2 = (flagsByte >> 1) & 1;
|
||||
flags.GanonsTower = (flagsByte >> 2) & 1;
|
||||
flags.TurtleRock = (flagsByte >> 3) & 1;
|
||||
flags.GargoylesDomain = (flagsByte >> 4) & 1;
|
||||
flags.TowerOfHera = (flagsByte >> 5) & 1;
|
||||
flags.IcePalace = (flagsByte >> 6) & 1;
|
||||
flags.SkullWoods = (flagsByte >> 7) & 1;
|
||||
flagsByte = base::readUByte();
|
||||
flags.MiseryMire = flagsByte & 1;
|
||||
flags.DarkPalace = (flagsByte >> 1) & 1;
|
||||
flags.SwampPalace = (flagsByte >> 2) & 1;
|
||||
flags.HyruleCastle2 = (flagsByte >> 3) & 1;
|
||||
flags.DesertPalace = (flagsByte >> 4) & 1;
|
||||
flags.EasternPalace = (flagsByte >> 5) & 1;
|
||||
flags.HyruleCastle = (flagsByte >> 6) & 1;
|
||||
flags.SewerPassage = (flagsByte >> 7) & 1;
|
||||
|
||||
aDebug() << std::hex << flags.flags1 << " " << flags.flags2 << std::dec << std::endl;
|
||||
return flags;
|
||||
|
|
|
@ -72,22 +72,26 @@ void ALTTPFileWriter::writeFile(ALTTPFile* file)
|
|||
base::writeByte(quest->healthFiller());
|
||||
base::writeByte(quest->magicFiller());
|
||||
ALTTPPendants pendants = quest->pendants();
|
||||
base::writeBit(pendants.Courage);
|
||||
base::writeBit(pendants.Wisdom);
|
||||
base::writeBit(pendants.Power);
|
||||
atUint8 pendantsByte = 0;
|
||||
pendantsByte |= pendants.Courage;
|
||||
pendantsByte |= pendants.Wisdom << 1;
|
||||
pendantsByte |= pendants.Power << 2;
|
||||
base::writeUByte(pendantsByte);
|
||||
base::writeByte(quest->bombFiller());
|
||||
base::writeByte(quest->arrowFiller());
|
||||
base::writeByte(quest->arrows());
|
||||
base::seek(1);
|
||||
ALTTPAbilities abilities = quest->abilityFlags();
|
||||
base::writeBit(abilities.Nothing);
|
||||
base::writeBit(abilities.Swim);
|
||||
base::writeBit(abilities.Dash);
|
||||
base::writeBit(abilities.Pull);
|
||||
base::writeBit(abilities.Unknown1);
|
||||
base::writeBit(abilities.Talk);
|
||||
base::writeBit(abilities.Read);
|
||||
base::writeBit(abilities.Unknown2);
|
||||
atUint8 abilitiesByte = 0;
|
||||
abilitiesByte |= abilities.Nothing;
|
||||
abilitiesByte |= abilities.Swim << 1;
|
||||
abilitiesByte |= abilities.Dash << 2;
|
||||
abilitiesByte |= abilities.Pull << 3;
|
||||
abilitiesByte |= abilities.Unknown1 << 4;
|
||||
abilitiesByte |= abilities.Talk << 5;
|
||||
abilitiesByte |= abilities.Read << 6;
|
||||
abilitiesByte |= abilities.Unknown2 << 7;
|
||||
base::writeUByte(abilitiesByte);
|
||||
ALTTPCrystals crystals = quest->crystals();
|
||||
base::writeBytes((atInt8*)&crystals, sizeof(ALTTPCrystals));
|
||||
ALTTPMagicUsage magicUsage = quest->magicUsage();
|
||||
|
@ -137,53 +141,63 @@ void ALTTPFileWriter::writeFile(ALTTPFile* file)
|
|||
|
||||
void ALTTPFileWriter::writeRoomFlags(ALTTPRoomFlags* flags)
|
||||
{
|
||||
base::writeBit(flags->Chest1);
|
||||
base::writeBit(flags->Chest2);
|
||||
base::writeBit(flags->Chest3);
|
||||
base::writeBit(flags->Chest4);
|
||||
base::writeBit(flags->Quadrant1);
|
||||
base::writeBit(flags->Quadrant2);
|
||||
base::writeBit(flags->Quadrant3);
|
||||
base::writeBit(flags->Quadrant4);
|
||||
base::writeBit(flags->Door1);
|
||||
base::writeBit(flags->Door2);
|
||||
base::writeBit(flags->Door3);
|
||||
base::writeBit(flags->Door4);
|
||||
base::writeBit(flags->BossBattleWon);
|
||||
base::writeBit(flags->Key);
|
||||
base::writeBit(flags->KeyOrChest);
|
||||
base::writeBit(flags->ChestOrTile);
|
||||
atUint8 flagsByte = 0;
|
||||
flagsByte |= flags->Chest1;
|
||||
flagsByte |= flags->Chest2 << 1;
|
||||
flagsByte |= flags->Chest3 << 2;
|
||||
flagsByte |= flags->Chest4 << 3;
|
||||
flagsByte |= flags->Quadrant1 << 4;
|
||||
flagsByte |= flags->Quadrant2 << 5;
|
||||
flagsByte |= flags->Quadrant3 << 6;
|
||||
flagsByte |= flags->Quadrant4 << 7;
|
||||
base::writeUByte(flagsByte);
|
||||
flagsByte = 0;
|
||||
flagsByte |= flags->Door1;
|
||||
flagsByte |= flags->Door2 << 1;
|
||||
flagsByte |= flags->Door3 << 2;
|
||||
flagsByte |= flags->Door4 << 3;
|
||||
flagsByte |= flags->BossBattleWon << 4;
|
||||
flagsByte |= flags->Key << 5;
|
||||
flagsByte |= flags->KeyOrChest << 6;
|
||||
flagsByte |= flags->ChestOrTile << 7;
|
||||
base::writeUByte(flagsByte);
|
||||
}
|
||||
|
||||
void ALTTPFileWriter::writeOverworldEvent(ALTTPOverworldEvent* event)
|
||||
{
|
||||
base::writeBit(event->Unused1);
|
||||
base::writeBit(event->HeartPiece);
|
||||
base::writeBit(event->Overlay);
|
||||
base::writeBit(event->Unused2);
|
||||
base::writeBit(event->Unused3);
|
||||
base::writeBit(event->Unused4);
|
||||
base::writeBit(event->Set);
|
||||
base::writeBit(event->Unused5);
|
||||
atUint8 flagsByte = 0;
|
||||
flagsByte |= event->Unused1;
|
||||
flagsByte |= event->HeartPiece << 1;
|
||||
flagsByte |= event->Overlay << 2;
|
||||
flagsByte |= event->Unused2 << 3;
|
||||
flagsByte |= event->Unused3 << 4;
|
||||
flagsByte |= event->Unused4 << 5;
|
||||
flagsByte |= event->Set << 6;
|
||||
flagsByte |= event->Unused5 << 7;
|
||||
base::writeUByte(flagsByte);
|
||||
}
|
||||
|
||||
void ALTTPFileWriter::writeDungeonItems(ALTTPDungeonItemFlags flags)
|
||||
{
|
||||
base::writeBit(flags.Unused1);
|
||||
base::writeBit(flags.Unused2);
|
||||
base::writeBit(flags.GanonsTower);
|
||||
base::writeBit(flags.TurtleRock);
|
||||
base::writeBit(flags.TowerOfHera);
|
||||
base::writeBit(flags.IcePalace);
|
||||
base::writeBit(flags.SkullWoods);
|
||||
base::writeBit(flags.MiseryMire);
|
||||
base::writeBit(flags.DarkPalace);
|
||||
base::writeBit(flags.SwampPalace);
|
||||
base::writeBit(flags.HyruleCastle2);
|
||||
base::writeBit(flags.DesertPalace);
|
||||
base::writeBit(flags.EasternPalace);
|
||||
base::writeBit(flags.HyruleCastle);
|
||||
base::writeBit(flags.SewerPassage);
|
||||
atUint8 flagsByte = 0;
|
||||
flagsByte |= flags.Unused1;
|
||||
flagsByte |= flags.Unused2 << 1;
|
||||
flagsByte |= flags.GanonsTower << 2;
|
||||
flagsByte |= flags.TurtleRock << 3;
|
||||
flagsByte |= flags.TowerOfHera << 4;
|
||||
flagsByte |= flags.IcePalace << 5;
|
||||
flagsByte |= flags.SkullWoods << 6;
|
||||
flagsByte |= flags.MiseryMire << 7;
|
||||
base::writeUByte(flagsByte);
|
||||
flagsByte = 0;
|
||||
flagsByte |= flags.DarkPalace;
|
||||
flagsByte |= flags.SwampPalace << 1;
|
||||
flagsByte |= flags.HyruleCastle2 << 2;
|
||||
flagsByte |= flags.DesertPalace << 3;
|
||||
flagsByte |= flags.EasternPalace << 4;
|
||||
flagsByte |= flags.HyruleCastle << 5;
|
||||
flagsByte |= flags.SewerPassage << 6;
|
||||
base::writeUByte(flagsByte);
|
||||
}
|
||||
|
||||
atUint16 ALTTPFileWriter::calculateChecksum(atUint32 game)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include "Athena/InvalidDataException.hpp"
|
||||
#include "Athena/InvalidOperationException.hpp"
|
||||
#include "Athena/IOException.hpp"
|
||||
#include "utf8.h"
|
||||
|
||||
#if _WIN32
|
||||
#include "win32_largefilewrapper.h"
|
||||
|
@ -17,9 +16,7 @@ namespace io
|
|||
{
|
||||
FileReader::FileReader(const std::string& filename)
|
||||
: m_filename(filename),
|
||||
m_fileHandle(NULL),
|
||||
m_endian(Endian::LittleEndian),
|
||||
m_bitValid(false)
|
||||
m_fileHandle(NULL)
|
||||
{
|
||||
open();
|
||||
}
|
||||
|
@ -57,14 +54,6 @@ void FileReader::seek(atInt64 pos, SeekOrigin origin)
|
|||
THROW_INVALID_OPERATION_EXCEPTION("Unable to seek in file");
|
||||
}
|
||||
|
||||
bool FileReader::atEnd() const
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(true, "File not open");
|
||||
|
||||
return feof(m_fileHandle) != 0;
|
||||
}
|
||||
|
||||
atUint64 FileReader::position() const
|
||||
{
|
||||
if (!isOpen())
|
||||
|
@ -81,259 +70,13 @@ atUint64 FileReader::length() const
|
|||
return utility::fileSize(m_filename);
|
||||
}
|
||||
|
||||
void FileReader::seekBit(int bit)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open");
|
||||
|
||||
if (bit < 0 || bit > 7)
|
||||
THROW_INVALID_OPERATION_EXCEPTION("bit out of range");
|
||||
|
||||
m_bitShift = bit;
|
||||
}
|
||||
|
||||
bool FileReader::readBit()
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(false, "File is not open for reading");
|
||||
|
||||
if (!m_bitValid)
|
||||
{
|
||||
size_t size = fread(&m_currentByte, 1, 1, m_fileHandle);
|
||||
|
||||
if (size != sizeof(atUint8))
|
||||
THROW_IO_EXCEPTION_RETURN(false, "Error reading from file.");
|
||||
|
||||
m_bitShift = 0;
|
||||
m_bitValid = true;
|
||||
}
|
||||
|
||||
atUint8 flag = (1 << m_bitShift);
|
||||
m_bitShift++;
|
||||
|
||||
if (m_bitShift > 7)
|
||||
m_bitValid = false;
|
||||
|
||||
return ((m_currentByte & flag) == flag);
|
||||
}
|
||||
|
||||
atUint8 FileReader::readUByte()
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading");
|
||||
|
||||
m_bitValid = false;
|
||||
atUint8 val = 0;
|
||||
fread(&val, 1, 1, m_fileHandle);
|
||||
return val;
|
||||
}
|
||||
|
||||
atUint8* FileReader::readUBytes(atUint64 len)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(nullptr, "File not open for reading");
|
||||
|
||||
m_bitValid = false;
|
||||
atUint8* val = new atUint8[len];
|
||||
fread(val, 1, len, m_fileHandle);
|
||||
return val;
|
||||
}
|
||||
|
||||
atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading");
|
||||
|
||||
m_bitValid = false;
|
||||
return fread(buf, 1, len, m_fileHandle);
|
||||
}
|
||||
|
||||
atUint16 FileReader::readUint16()
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading");
|
||||
|
||||
m_bitValid = false;
|
||||
atUint16 val;
|
||||
fread(&val, 1, sizeof(atUint16), m_fileHandle);
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
val = utility::swapU16(val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
atUint32 FileReader::readUint32()
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading");
|
||||
|
||||
m_bitValid = false;
|
||||
atUint32 val;
|
||||
fread(&val, 1, sizeof(atUint32), m_fileHandle);
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
val = utility::swapU32(val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
atUint64 FileReader::readUint64()
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading");
|
||||
|
||||
m_bitValid = false;
|
||||
atUint64 val;
|
||||
fread(&val, 1, sizeof(atUint64), m_fileHandle);
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
val = utility::swapU64(val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
double FileReader::readDouble()
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading");
|
||||
|
||||
m_bitValid = false;
|
||||
double val;
|
||||
fread(&val, 1, sizeof(double), m_fileHandle);
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
val = utility::swapDouble(val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
float FileReader::readFloat()
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading");
|
||||
|
||||
m_bitValid = false;
|
||||
float val;
|
||||
fread(&val, 1, sizeof(float), m_fileHandle);
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
val = utility::swapFloat(val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
atVec3f FileReader::readVec3f()
|
||||
{
|
||||
atVec3f val = {};
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(val, "File not open for reading");
|
||||
|
||||
m_bitValid = false;
|
||||
fread(&val, 1, 12, m_fileHandle);
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
{
|
||||
val.vec[0] = utility::swapFloat(val.vec[0]);
|
||||
val.vec[1] = utility::swapFloat(val.vec[1]);
|
||||
val.vec[2] = utility::swapFloat(val.vec[2]);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
atVec4f FileReader::readVec4f()
|
||||
{
|
||||
atVec4f val = {};
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(val, "File not open for reading");
|
||||
|
||||
m_bitValid = false;
|
||||
fread(&val, 1, 16, m_fileHandle);
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
{
|
||||
val.vec[0] = utility::swapFloat(val.vec[0]);
|
||||
val.vec[1] = utility::swapFloat(val.vec[1]);
|
||||
val.vec[2] = utility::swapFloat(val.vec[2]);
|
||||
val.vec[3] = utility::swapFloat(val.vec[3]);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
std::string FileReader::readString(atInt32 fixedLen)
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
atUint8 chr = readByte();
|
||||
atInt32 i;
|
||||
for (i = 1 ; chr != 0 ; ++i)
|
||||
{
|
||||
ret += chr;
|
||||
|
||||
if (fixedLen >= 0 && i >= fixedLen)
|
||||
break;
|
||||
|
||||
chr = readByte();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::wstring FileReader::readWString(atInt32 fixedLen)
|
||||
{
|
||||
std::wstring ret;
|
||||
atUint16 chr = readUint16();
|
||||
|
||||
atInt32 i;
|
||||
for (i = 1 ; chr != 0 ; ++i)
|
||||
{
|
||||
ret += chr;
|
||||
|
||||
if (fixedLen >= 0 && i >= fixedLen)
|
||||
break;
|
||||
|
||||
chr = readUint16();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string FileReader::readUnicode(atInt32 fixedLen)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(std::string(), "File not open for reading");
|
||||
|
||||
std::string ret;
|
||||
std::vector<atUint16> tmp;
|
||||
atInt32 i;
|
||||
for (i = 0 ;; ++i)
|
||||
{
|
||||
if (fixedLen >= 0 && i >= fixedLen - 1)
|
||||
break;
|
||||
|
||||
atUint16 chr = readUint16();
|
||||
|
||||
if (chr)
|
||||
tmp.push_back(chr);
|
||||
else
|
||||
break;
|
||||
};
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
utf8::utf16to8(tmp.begin(), tmp.end(), back_inserter(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // io
|
||||
} // Athena
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
#include "osx_largefilewrapper.h"
|
||||
#endif
|
||||
|
||||
#include "utf8.h"
|
||||
|
||||
namespace Athena
|
||||
{
|
||||
namespace io
|
||||
|
@ -19,10 +17,7 @@ namespace io
|
|||
FileWriter::FileWriter(const std::string& filename, bool overwrite)
|
||||
: m_filename(filename),
|
||||
m_fileHandle(NULL),
|
||||
m_endian(Endian::LittleEndian),
|
||||
m_bytePosition(0),
|
||||
m_bitShift(0),
|
||||
m_bitValid(false)
|
||||
m_bytePosition(0)
|
||||
{
|
||||
open(overwrite);
|
||||
}
|
||||
|
@ -63,11 +58,6 @@ void FileWriter::seek(atInt64 pos, SeekOrigin origin)
|
|||
THROW_IO_EXCEPTION("Unable to seek in file");
|
||||
}
|
||||
|
||||
bool FileWriter::atEnd() const
|
||||
{
|
||||
return feof(m_fileHandle) != 0;
|
||||
}
|
||||
|
||||
atUint64 FileWriter::position() const
|
||||
{
|
||||
return ftello64(m_fileHandle);
|
||||
|
@ -78,292 +68,14 @@ atUint64 FileWriter::length() const
|
|||
return utility::fileSize(m_filename);
|
||||
}
|
||||
|
||||
void FileWriter::writeBit(bool val)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
if (!m_bitValid)
|
||||
{
|
||||
m_bitValid = true;
|
||||
m_bitShift = 0;
|
||||
m_bytePosition = ftello64(m_fileHandle);
|
||||
}
|
||||
|
||||
|
||||
if (val)
|
||||
m_currentByte |= (1 << m_bitShift++);
|
||||
else
|
||||
m_currentByte &= ~(1 << m_bitShift++);
|
||||
|
||||
if (m_bitShift > 7)
|
||||
m_bitValid = false;
|
||||
|
||||
fseeko64(m_fileHandle, m_bytePosition, (int)SeekOrigin::Begin);
|
||||
|
||||
if (fwrite(&m_currentByte, 1, 1, m_fileHandle) != sizeof(atInt8))
|
||||
THROW_IO_EXCEPTION("Unable to data to file");
|
||||
}
|
||||
|
||||
void FileWriter::seekBit(int bit)
|
||||
{
|
||||
if (bit < 0 || bit > 7)
|
||||
THROW_INVALID_OPERATION_EXCEPTION("bit must be >= 0 and <= 7");
|
||||
|
||||
m_bitShift = bit;
|
||||
m_bitValid = true;
|
||||
}
|
||||
|
||||
void FileWriter::writeUByte(atUint8 val)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
|
||||
if (fwrite(&val, 1, sizeof(atUint8), m_fileHandle) != sizeof(atUint8))
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
|
||||
void FileWriter::writeUBytes(const atUint8* data, atUint64 len)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
|
||||
if (fwrite(data, 1, len, m_fileHandle) != len)
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
|
||||
void FileWriter::writeUint16(atUint16 val)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
val = utility::swapU16(val);
|
||||
|
||||
if (fwrite(&val, 1, sizeof(atUint16), m_fileHandle) != sizeof(atUint16))
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
|
||||
void FileWriter::writeUint32(atUint32 val)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
val = utility::swapU32(val);
|
||||
|
||||
if (fwrite(&val, 1, sizeof(atUint32), m_fileHandle) != sizeof(atUint32))
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
|
||||
void FileWriter::writeUint64(atUint64 val)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
val = utility::swapU64(val);
|
||||
|
||||
if (fwrite(&val, 1, sizeof(atUint64), m_fileHandle) != sizeof(atUint64))
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
|
||||
void FileWriter::writeDouble(double val)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
val = utility::swapDouble(val);
|
||||
|
||||
if (fwrite(&val, 1, sizeof(double), m_fileHandle) != sizeof(double))
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
|
||||
void FileWriter::writeFloat(float val)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
val = utility::swapFloat(val);
|
||||
|
||||
if (fwrite(&val, 1, sizeof(float), m_fileHandle) != sizeof(float))
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
|
||||
void FileWriter::writeVec3f(atVec3f vec)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
{
|
||||
vec.vec[0] = utility::swapFloat(vec.vec[0]);
|
||||
vec.vec[1] = utility::swapFloat(vec.vec[1]);
|
||||
vec.vec[2] = utility::swapFloat(vec.vec[2]);
|
||||
}
|
||||
|
||||
if (fwrite(&vec, 1, 12, m_fileHandle) != 12)
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
|
||||
void FileWriter::writeVec4f(atVec4f vec)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
|
||||
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
|
||||
{
|
||||
vec.vec[0] = utility::swapFloat(vec.vec[0]);
|
||||
vec.vec[1] = utility::swapFloat(vec.vec[1]);
|
||||
vec.vec[2] = utility::swapFloat(vec.vec[2]);
|
||||
vec.vec[3] = utility::swapFloat(vec.vec[3]);
|
||||
}
|
||||
|
||||
if (fwrite(&vec, 1, 16, m_fileHandle) != 16)
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
|
||||
void FileWriter::writeString(const std::string& val, atInt32 fixedLen)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
char term = '\0';
|
||||
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
if (fwrite(val.c_str(), 1, val.length(), m_fileHandle) != val.length())
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
|
||||
if (fwrite(&term, 1, 1, m_fileHandle) != 1)
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((atInt32)val.length() >= fixedLen)
|
||||
{
|
||||
if ((atInt32)fwrite(val.c_str(), 1, fixedLen, m_fileHandle) != fixedLen)
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fwrite(val.c_str(), 1, val.length(), m_fileHandle) != val.length())
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
for (atInt32 i=val.length() ; i<fixedLen ; ++i)
|
||||
{
|
||||
if (fwrite(&term, 1, 1, m_fileHandle) != 1)
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileWriter::writeWString(const std::wstring& val, atInt32 fixedLen)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
m_bitValid = false;
|
||||
wchar_t term = L'\0';
|
||||
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
if (fwrite(val.c_str(), 2, val.length(), m_fileHandle) != val.length())
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
|
||||
if (fwrite(&term, 2, 1, m_fileHandle) != 1)
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((atInt32)val.length() >= fixedLen)
|
||||
{
|
||||
if ((atInt32)fwrite(val.c_str(), 2, fixedLen, m_fileHandle) != fixedLen)
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fwrite(val.c_str(), 2, val.length(), m_fileHandle) != val.length())
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
for (atInt32 i=val.length() ; i<fixedLen ; ++i)
|
||||
{
|
||||
if (fwrite(&term, 2, 1, m_fileHandle) != 1)
|
||||
THROW_IO_EXCEPTION("Unable to write to stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileWriter::writeUnicode(const std::string& str, atInt32 fixedLen)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
std::string tmpStr = "\xEF\xBB\xBF" + str;
|
||||
|
||||
std::vector<atUint16> tmp;
|
||||
|
||||
utf8::utf8to16(tmpStr.begin(), tmpStr.end(), back_inserter(tmp));
|
||||
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
for (atUint16 chr : tmp)
|
||||
{
|
||||
if (chr != 0xFEFF)
|
||||
writeUint16(chr);
|
||||
}
|
||||
writeUint16(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = tmp.begin();
|
||||
for (atInt32 i=0 ; i<fixedLen ; ++i)
|
||||
{
|
||||
atUint16 chr;
|
||||
if (it == tmp.end())
|
||||
chr = 0;
|
||||
else
|
||||
chr = *it++;
|
||||
|
||||
if (chr == 0xFEFF)
|
||||
{
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
writeUint16(chr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileWriter::fill(atInt8 byte, atUint64 len)
|
||||
{
|
||||
if (!isOpen())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
|
||||
|
||||
fwrite(&byte, 1, len, m_fileHandle);
|
||||
}
|
||||
|
||||
}
|
||||
} // Athena
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include "Athena/FileNotFoundException.hpp"
|
||||
#include "Athena/InvalidDataException.hpp"
|
||||
#include "Athena/InvalidOperationException.hpp"
|
||||
#include "utf8.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -21,10 +20,7 @@ namespace io
|
|||
{
|
||||
MemoryReader::MemoryReader(const atUint8* data, atUint64 length)
|
||||
: m_length(length),
|
||||
m_position(0),
|
||||
m_bitPosition(0),
|
||||
m_endian(Endian::LittleEndian),
|
||||
m_progressCallback(nullptr)
|
||||
m_position(0)
|
||||
{
|
||||
if (!data)
|
||||
THROW_INVALID_DATA_EXCEPTION("data cannot be NULL");
|
||||
|
@ -36,14 +32,11 @@ MemoryReader::MemoryReader(const atUint8* data, atUint64 length)
|
|||
memcpy(m_data, data, m_length);
|
||||
}
|
||||
|
||||
MemoryReader::MemoryReader(const std::string& filename, std::function<void(int)> progFun)
|
||||
MemoryReader::MemoryReader(const std::string& filename)
|
||||
: m_data(NULL),
|
||||
m_length(0),
|
||||
m_filepath(filename),
|
||||
m_position(0),
|
||||
m_bitPosition(0),
|
||||
m_endian(Endian::LittleEndian),
|
||||
m_progressCallback(progFun)
|
||||
m_position(0)
|
||||
{
|
||||
loadData();
|
||||
}
|
||||
|
@ -89,7 +82,6 @@ void MemoryReader::setData(const atUint8* data, atUint64 length)
|
|||
m_data = (atUint8*)data;
|
||||
m_length = length;
|
||||
m_position = 0;
|
||||
m_bitPosition = 0;
|
||||
}
|
||||
|
||||
atUint8* MemoryReader::data() const
|
||||
|
@ -100,108 +92,11 @@ atUint8* MemoryReader::data() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
void MemoryReader::seekBit(int bit)
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (bit < 0 || bit > 7)
|
||||
THROW_INVALID_OPERATION_EXCEPTION("bit out of range %i %s", bit, (bit < 0 ? "< 0" : "> 7"));
|
||||
|
||||
m_bitPosition = bit;
|
||||
}
|
||||
|
||||
bool MemoryReader::readBit()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_position > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(false, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
bool ret = (*(atUint8*)(m_data + m_position) & (1 << m_bitPosition)) != 0;
|
||||
|
||||
m_bitPosition++;
|
||||
|
||||
if (m_bitPosition > 7)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
atInt8 MemoryReader::readByte()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + 1 > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
return *(atInt8*)(m_data + m_position++);
|
||||
}
|
||||
|
||||
atUint8 MemoryReader::readUByte()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + 1 > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
return *(atUint8*)(m_data + m_position++);
|
||||
}
|
||||
|
||||
atUint8* MemoryReader::readUBytes(atUint64 length)
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + length > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(nullptr, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
atUint8* ret;
|
||||
ret = new atUint8[length];
|
||||
|
||||
memcpy(ret, (const atUint8*)(m_data + m_position), length);
|
||||
m_position += length;
|
||||
return ret;
|
||||
}
|
||||
|
||||
atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length)
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + length > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
|
@ -210,298 +105,6 @@ atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length)
|
|||
return length;
|
||||
}
|
||||
|
||||
atInt16 MemoryReader::readInt16()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(atInt16) > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
atInt16 ret = *(atInt16*)(m_data + m_position);
|
||||
m_position += sizeof(atInt16);
|
||||
|
||||
if (isBigEndian())
|
||||
utility::BigInt16(ret);
|
||||
else
|
||||
utility::LittleInt16(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
atInt32 MemoryReader::readInt32()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(atInt32) > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
atInt32 ret = *(atInt32*)(m_data + m_position);
|
||||
m_position += 4;
|
||||
|
||||
if (isBigEndian())
|
||||
utility::BigInt32(ret);
|
||||
else
|
||||
utility::LittleInt32(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
atInt64 MemoryReader::readInt64()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(atInt64) > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
atInt64 ret = *(atInt64*)(m_data + m_position);
|
||||
m_position += 8;
|
||||
|
||||
if (isBigEndian())
|
||||
utility::BigInt64(ret);
|
||||
else
|
||||
utility::LittleInt64(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
float MemoryReader::readFloat()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(float) > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
float ret = *(float*)(m_data + m_position);
|
||||
m_position += 4;
|
||||
|
||||
if (isBigEndian())
|
||||
utility::BigFloat(ret);
|
||||
else
|
||||
utility::LittleFloat(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
double MemoryReader::readDouble()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(double) > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
double ret = *(double*)(m_data + m_position);
|
||||
m_position += 8;
|
||||
|
||||
if (isBigEndian())
|
||||
utility::BigDouble(ret);
|
||||
else
|
||||
utility::LittleDouble(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MemoryReader::readBool()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(bool) > m_length)
|
||||
THROW_IO_EXCEPTION_RETURN(false, "Position %0.8X outside stream bounds ", m_position);
|
||||
|
||||
bool ret = *(bool*)(m_data + m_position);
|
||||
m_position += 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
atVec3f MemoryReader::readVec3f()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + 12 > m_length)
|
||||
{
|
||||
atVec3f zero = {};
|
||||
THROW_IO_EXCEPTION_RETURN(zero, "Position %0.8X outside stream bounds ", m_position);
|
||||
}
|
||||
|
||||
float* source = (float*)(m_data + m_position);
|
||||
atVec3f result = {source[0], source[1], source[2]};
|
||||
if (isBigEndian())
|
||||
{
|
||||
utility::BigFloat(result.vec[0]);
|
||||
utility::BigFloat(result.vec[1]);
|
||||
utility::BigFloat(result.vec[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
utility::LittleFloat(result.vec[0]);
|
||||
utility::LittleFloat(result.vec[1]);
|
||||
utility::LittleFloat(result.vec[2]);
|
||||
}
|
||||
|
||||
m_position += 12;
|
||||
return result;
|
||||
}
|
||||
|
||||
atVec4f MemoryReader::readVec4f()
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + 16 > m_length)
|
||||
{
|
||||
atVec4f zero = {};
|
||||
THROW_IO_EXCEPTION_RETURN(zero, "Position %0.8X outside stream bounds ", m_position);
|
||||
}
|
||||
|
||||
float* source = (float*)(m_data + m_position);
|
||||
atVec4f result = {source[0], source[1], source[2], source[3]};
|
||||
if (isBigEndian())
|
||||
{
|
||||
utility::BigFloat(result.vec[0]);
|
||||
utility::BigFloat(result.vec[1]);
|
||||
utility::BigFloat(result.vec[2]);
|
||||
utility::BigFloat(result.vec[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
utility::LittleFloat(result.vec[0]);
|
||||
utility::LittleFloat(result.vec[1]);
|
||||
utility::LittleFloat(result.vec[2]);
|
||||
utility::LittleFloat(result.vec[3]);
|
||||
}
|
||||
|
||||
m_position += 16;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string MemoryReader::readUnicode(atInt32 fixedLen)
|
||||
{
|
||||
if (!m_data)
|
||||
loadData();
|
||||
|
||||
std::string ret;
|
||||
std::vector<short> tmp;
|
||||
atUint16 chr = readUint16();
|
||||
|
||||
atInt32 i;
|
||||
for (i = 0 ;; ++i)
|
||||
{
|
||||
if (fixedLen >= 0 && i >= fixedLen - 1)
|
||||
break;
|
||||
|
||||
if (!chr)
|
||||
break;
|
||||
|
||||
tmp.push_back(chr);
|
||||
chr = readUint16();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
utf8::utf16to8(tmp.begin(), tmp.end(), back_inserter(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string MemoryReader::readString(atInt32 fixedLen)
|
||||
{
|
||||
std::string ret;
|
||||
atUint8 chr = readByte();
|
||||
|
||||
atInt32 i;
|
||||
for (i = 1 ; chr != 0 ; ++i)
|
||||
{
|
||||
ret += chr;
|
||||
|
||||
if (fixedLen >= 0 && i >= fixedLen)
|
||||
break;
|
||||
|
||||
chr = readByte();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::wstring MemoryReader::readWString(atInt32 fixedLen)
|
||||
{
|
||||
std::wstring ret;
|
||||
atUint16 chr = readUint16();
|
||||
|
||||
atInt32 i;
|
||||
for (i = 1 ; chr != 0 ; ++i)
|
||||
{
|
||||
ret += chr;
|
||||
|
||||
if (fixedLen >= 0 && i >= fixedLen)
|
||||
break;
|
||||
|
||||
chr = readUint16();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MemoryReader::loadData()
|
||||
{
|
||||
FILE* in;
|
||||
|
@ -533,8 +136,6 @@ void MemoryReader::loadData()
|
|||
|
||||
done += ret;
|
||||
|
||||
if (m_progressCallback)
|
||||
m_progressCallback((int)((float)(done * 100.f) / length));
|
||||
|
||||
}
|
||||
while (done < length);
|
||||
|
@ -542,7 +143,6 @@ void MemoryReader::loadData()
|
|||
fclose(in);
|
||||
m_length = length;
|
||||
m_position = 0;
|
||||
m_bitPosition = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include "Athena/InvalidOperationException.hpp"
|
||||
#include "Athena/InvalidDataException.hpp"
|
||||
#include "Athena/FileNotFoundException.hpp"
|
||||
#include "utf8.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -22,10 +21,7 @@ namespace io
|
|||
MemoryWriter::MemoryWriter(atUint8* data, atUint64 length)
|
||||
: m_data((atUint8*)data),
|
||||
m_length(length),
|
||||
m_position(0),
|
||||
m_bitPosition(0),
|
||||
m_endian(Endian::LittleEndian),
|
||||
m_progressCallback(nullptr)
|
||||
m_position(0)
|
||||
{
|
||||
if (!m_data && m_length > 0)
|
||||
m_data = new atUint8[m_length];
|
||||
|
@ -34,13 +30,9 @@ MemoryWriter::MemoryWriter(atUint8* data, atUint64 length)
|
|||
MemoryWriter::MemoryWriter(const std::string& filename, std::function<void(int)> progressFun)
|
||||
: m_length(0),
|
||||
m_filepath(filename),
|
||||
m_position(0),
|
||||
m_bitPosition(0),
|
||||
m_endian(Endian::LittleEndian),
|
||||
m_progressCallback(progressFun)
|
||||
m_position(0)
|
||||
{
|
||||
m_length = 0x10;
|
||||
m_bitPosition = 0;
|
||||
m_position = 0;
|
||||
m_data = new atUint8[m_length];
|
||||
|
||||
|
@ -100,7 +92,6 @@ void MemoryWriter::setData(const atUint8* data, atUint64 length)
|
|||
m_data = (atUint8*)data;
|
||||
m_length = length;
|
||||
m_position = 0;
|
||||
m_bitPosition = 0;
|
||||
}
|
||||
|
||||
atUint8* MemoryWriter::data() const
|
||||
|
@ -150,66 +141,11 @@ void MemoryWriter::save(const std::string& filename)
|
|||
fclose(out);
|
||||
}
|
||||
|
||||
void MemoryWriter::seekBit(int bit)
|
||||
{
|
||||
if (bit < 0 || bit > 7)
|
||||
THROW_INVALID_OPERATION_EXCEPTION("bit out of range");
|
||||
|
||||
m_bitPosition = bit;
|
||||
}
|
||||
|
||||
void MemoryWriter::writeBit(bool val)
|
||||
{
|
||||
if (!isOpen())
|
||||
resize(sizeof(atUint8));
|
||||
|
||||
if (m_position + sizeof(atUint8) > m_length)
|
||||
resize(m_position + sizeof(atUint8));
|
||||
|
||||
if (val)
|
||||
*(atUint8*)(m_data + m_position) |= (1 << m_bitPosition);
|
||||
else
|
||||
*(atUint8*)(m_data + m_position) &= ~(1 << m_bitPosition);
|
||||
|
||||
m_bitPosition++;
|
||||
|
||||
if (m_bitPosition > 7)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryWriter::writeUByte(atUint8 val)
|
||||
{
|
||||
if (!isOpen())
|
||||
resize(sizeof(atUint8));
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + 1 > m_length)
|
||||
resize(m_position + 1);
|
||||
|
||||
*(atUint8*)(m_data + m_position) = val;
|
||||
|
||||
m_position++;
|
||||
}
|
||||
|
||||
void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length)
|
||||
{
|
||||
if (!isOpen())
|
||||
resize(sizeof(atUint8) * length);
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (!data)
|
||||
THROW_INVALID_DATA_EXCEPTION("data cannnot be NULL");
|
||||
|
||||
|
@ -221,309 +157,6 @@ void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length)
|
|||
m_position += length;
|
||||
}
|
||||
|
||||
void MemoryWriter::writeInt16(atInt16 val)
|
||||
{
|
||||
if (!isOpen())
|
||||
resize(sizeof(atInt16));
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(atInt16) > m_length)
|
||||
resize(m_position + sizeof(atInt16));
|
||||
|
||||
if (isBigEndian())
|
||||
utility::BigInt16(val);
|
||||
else
|
||||
utility::LittleInt16(val);
|
||||
|
||||
*(atInt16*)(m_data + m_position) = val;
|
||||
m_position += sizeof(atInt16);
|
||||
}
|
||||
|
||||
void MemoryWriter::writeInt32(atInt32 val)
|
||||
{
|
||||
if (!isOpen())
|
||||
resize(sizeof(atInt32));
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(atInt32) > m_length)
|
||||
resize(m_position + sizeof(atInt32));
|
||||
|
||||
if (isBigEndian())
|
||||
utility::BigInt32(val);
|
||||
else
|
||||
utility::LittleInt32(val);
|
||||
|
||||
*(atInt32*)(m_data + m_position) = val;
|
||||
m_position += sizeof(atInt32);
|
||||
}
|
||||
|
||||
void MemoryWriter::writeInt64(atInt64 val)
|
||||
{
|
||||
if (!isOpen())
|
||||
resize(sizeof(atInt64));
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(atInt64) > m_length)
|
||||
resize(m_position + sizeof(atInt64));
|
||||
|
||||
|
||||
if (isBigEndian())
|
||||
utility::BigInt64(val);
|
||||
else
|
||||
utility::LittleInt64(val);
|
||||
|
||||
*(atInt64*)(m_data + m_position) = val;
|
||||
m_position += sizeof(atInt64);
|
||||
}
|
||||
|
||||
void MemoryWriter::writeFloat(float val)
|
||||
{
|
||||
if (!isOpen())
|
||||
resize(sizeof(float));
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(float) > m_length)
|
||||
resize(m_position + sizeof(float));
|
||||
|
||||
if (isBigEndian())
|
||||
utility::BigFloat(val);
|
||||
else
|
||||
utility::LittleFloat(val);
|
||||
|
||||
|
||||
*(float*)(m_data + m_position) = val;
|
||||
m_position += sizeof(float);
|
||||
}
|
||||
|
||||
void MemoryWriter::writeDouble(double val)
|
||||
{
|
||||
if (!isOpen())
|
||||
resize(sizeof(double));
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(double) > m_length)
|
||||
resize(m_position + sizeof(double));
|
||||
|
||||
if (isBigEndian())
|
||||
utility::BigDouble(val);
|
||||
else
|
||||
utility::LittleDouble(val);
|
||||
|
||||
*(double*)(m_data + m_position) = val;
|
||||
m_position += sizeof(double);
|
||||
}
|
||||
|
||||
void MemoryWriter::writeBool(bool val)
|
||||
{
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + sizeof(bool) > m_length)
|
||||
resize(m_position + sizeof(bool));
|
||||
|
||||
*(bool*)(m_data + m_position) = val;
|
||||
m_position += sizeof(bool);
|
||||
}
|
||||
|
||||
void MemoryWriter::writeVec3f(atVec3f vec)
|
||||
{
|
||||
if (!isOpen())
|
||||
resize(12);
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + 12 > m_length)
|
||||
resize(m_position + 12);
|
||||
|
||||
if (isBigEndian())
|
||||
{
|
||||
utility::BigFloat(vec.vec[0]);
|
||||
utility::BigFloat(vec.vec[1]);
|
||||
utility::BigFloat(vec.vec[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
utility::LittleFloat(vec.vec[0]);
|
||||
utility::LittleFloat(vec.vec[1]);
|
||||
utility::LittleFloat(vec.vec[2]);
|
||||
}
|
||||
|
||||
((float*)(m_data + m_position))[0] = vec.vec[0];
|
||||
((float*)(m_data + m_position))[1] = vec.vec[1];
|
||||
((float*)(m_data + m_position))[2] = vec.vec[2];
|
||||
m_position += 12;
|
||||
}
|
||||
|
||||
void MemoryWriter::writeVec4f(atVec4f vec)
|
||||
{
|
||||
if (!isOpen())
|
||||
resize(16);
|
||||
|
||||
if (m_bitPosition > 0)
|
||||
{
|
||||
m_bitPosition = 0;
|
||||
m_position += sizeof(atUint8);
|
||||
}
|
||||
|
||||
if (m_position + 16 > m_length)
|
||||
resize(m_position + 16);
|
||||
|
||||
if (isBigEndian())
|
||||
{
|
||||
utility::BigFloat(vec.vec[0]);
|
||||
utility::BigFloat(vec.vec[1]);
|
||||
utility::BigFloat(vec.vec[2]);
|
||||
utility::BigFloat(vec.vec[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
utility::LittleFloat(vec.vec[0]);
|
||||
utility::LittleFloat(vec.vec[1]);
|
||||
utility::LittleFloat(vec.vec[2]);
|
||||
utility::LittleFloat(vec.vec[3]);
|
||||
}
|
||||
|
||||
((float*)(m_data + m_position))[0] = vec.vec[0];
|
||||
((float*)(m_data + m_position))[1] = vec.vec[1];
|
||||
((float*)(m_data + m_position))[2] = vec.vec[2];
|
||||
((float*)(m_data + m_position))[3] = vec.vec[3];
|
||||
m_position += 16;
|
||||
}
|
||||
|
||||
void MemoryWriter::writeUnicode(const std::string& str, atInt32 fixedLen)
|
||||
{
|
||||
std::string tmpStr = "\xEF\xBB\xBF" + str;
|
||||
|
||||
std::vector<atUint16> tmp;
|
||||
|
||||
utf8::utf8to16(tmpStr.begin(), tmpStr.end(), back_inserter(tmp));
|
||||
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
for (atUint16 chr : tmp)
|
||||
{
|
||||
if (chr != 0xFEFF)
|
||||
writeUint16(chr);
|
||||
}
|
||||
writeUint16(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = tmp.begin();
|
||||
for (atInt32 i=0 ; i<fixedLen ; ++i)
|
||||
{
|
||||
atUint16 chr;
|
||||
if (it == tmp.end())
|
||||
chr = 0;
|
||||
else
|
||||
chr = *it++;
|
||||
|
||||
if (chr == 0xFEFF)
|
||||
{
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
writeUint16(chr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MemoryWriter::writeString(const std::string& str, atInt32 fixedLen)
|
||||
{
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
for (atUint8 c : str)
|
||||
{
|
||||
writeUByte(c);
|
||||
|
||||
if (c == '\0')
|
||||
break;
|
||||
}
|
||||
writeUByte(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = str.begin();
|
||||
for (atInt32 i=0 ; i<fixedLen ; ++i)
|
||||
{
|
||||
atUint8 chr;
|
||||
if (it == str.end())
|
||||
chr = 0;
|
||||
else
|
||||
chr = *it++;
|
||||
writeUByte(chr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryWriter::writeWString(const std::wstring& str, atInt32 fixedLen)
|
||||
{
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
for (atUint16 c : str)
|
||||
{
|
||||
writeUint16(c);
|
||||
|
||||
if (c == L'\0')
|
||||
break;
|
||||
}
|
||||
writeUint16(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = str.begin();
|
||||
for (atInt32 i=0 ; i<fixedLen ; ++i)
|
||||
{
|
||||
atUint16 chr;
|
||||
if (it == str.end())
|
||||
chr = 0;
|
||||
else
|
||||
chr = *it++;
|
||||
writeUint16(chr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryWriter::fill(atUint8 val, atUint64 length)
|
||||
{
|
||||
while ((length--) > 0)
|
||||
writeUByte(val);
|
||||
}
|
||||
|
||||
void MemoryWriter::resize(atUint64 newSize)
|
||||
{
|
||||
if (newSize < m_length)
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
#include "Athena/SkywardSwordQuest.hpp"
|
||||
#include "Athena/Checksums.hpp"
|
||||
#include <sstream>
|
||||
#include "utf8.h"
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
|
||||
namespace Athena
|
||||
{
|
||||
|
||||
|
@ -79,8 +81,8 @@ void SkywardSwordQuest::setPlayerName(const std::string& name)
|
|||
if (name.length() > 8)
|
||||
aDebug() << "WARNING: name cannot be greater than 8 characters, automatically truncating" << std::endl;
|
||||
|
||||
std::vector<atUint16> val;
|
||||
utf8::utf8to16(name.begin(), name.end(), std::back_inserter(val));
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
std::wstring val = conv.from_bytes(name);
|
||||
|
||||
for (atUint32 i = 0; i < 8; i++)
|
||||
{
|
||||
|
@ -99,7 +101,7 @@ void SkywardSwordQuest::setPlayerName(const std::string& name)
|
|||
|
||||
std::string SkywardSwordQuest::playerName() const
|
||||
{
|
||||
std::vector<atUint16> val;
|
||||
std::wstring val;
|
||||
|
||||
for (atUint32 i = 0; i < 8; i++)
|
||||
{
|
||||
|
@ -112,9 +114,8 @@ std::string SkywardSwordQuest::playerName() const
|
|||
val.push_back(c);
|
||||
}
|
||||
|
||||
std::string ret;
|
||||
utf8::utf16to8(val.begin(), val.end(), std::back_inserter(ret));
|
||||
return std::string(ret.c_str());
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
return conv.to_bytes(val);
|
||||
}
|
||||
|
||||
void SkywardSwordQuest::setRupeeCount(atUint16 value)
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "Athena/MemoryReader.hpp"
|
||||
#include "Athena/MemoryWriter.hpp"
|
||||
#include "Athena/Utility.hpp"
|
||||
#include "aes.h"
|
||||
#include "aes.hpp"
|
||||
#include "ec.h"
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "Athena/InvalidDataException.hpp"
|
||||
#include "Athena/FileWriter.hpp"
|
||||
#include "md5.h"
|
||||
#include "aes.h"
|
||||
#include "aes.hpp"
|
||||
#include "ec.h"
|
||||
#include "sha1.h"
|
||||
#include <iostream>
|
||||
|
@ -129,8 +129,9 @@ WiiBanner* WiiSaveReader::readBanner()
|
|||
memcpy(tmpIV, SD_IV, 16);
|
||||
|
||||
std::cout << "Decrypting: banner.bin...";
|
||||
aes_set_key(SD_KEY);
|
||||
aes_decrypt(tmpIV, data, dec, 0xF0C0);
|
||||
std::unique_ptr<IAES> aes = NewAES();
|
||||
aes->setKey(SD_KEY);
|
||||
aes->decrypt(tmpIV, data, dec, 0xF0C0);
|
||||
std::cout << "done" << std::endl;
|
||||
|
||||
memset(md5, 0, 16);
|
||||
|
@ -296,8 +297,9 @@ WiiFile* WiiSaveReader::readFile()
|
|||
// Decrypt file
|
||||
std::cout << "Decrypting: " << ret->filename() << "...";
|
||||
atUint8* decData = new atUint8[roundedLen];
|
||||
aes_set_key(SD_KEY);
|
||||
aes_decrypt(iv, filedata, decData, roundedLen);
|
||||
std::unique_ptr<IAES> aes = NewAES();
|
||||
aes->setKey(SD_KEY);
|
||||
aes->decrypt(iv, filedata, decData, roundedLen);
|
||||
delete filedata;
|
||||
ret->setData(decData);
|
||||
ret->setLength(fileLen);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "Athena/InvalidOperationException.hpp"
|
||||
#include "Athena/InvalidDataException.hpp"
|
||||
|
||||
#include "aes.h"
|
||||
#include "aes.hpp"
|
||||
#include "ec.h"
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
|
@ -146,12 +146,13 @@ void WiiSaveWriter::writeBanner(WiiBanner* banner)
|
|||
base::seek(0x0E, SeekOrigin::Begin);
|
||||
base::writeBytes((atInt8*)hash, 0x10);
|
||||
|
||||
aes_set_key(SD_KEY);
|
||||
std::unique_ptr<IAES> aes = NewAES();
|
||||
aes->setKey(SD_KEY);
|
||||
atUint8 data[0xF0C0];
|
||||
memcpy(data, base::data(), 0xF0C0);
|
||||
atUint8 tmpIV[26];
|
||||
memcpy(tmpIV, SD_IV, 16);
|
||||
aes_encrypt(tmpIV, data, data, 0xF0C0);
|
||||
aes->encrypt(tmpIV, data, data, 0xF0C0);
|
||||
|
||||
base::seek(0, SeekOrigin::Begin);
|
||||
base::writeBytes((atInt8*)data, 0xF0C0);
|
||||
|
@ -187,8 +188,9 @@ atUint32 WiiSaveWriter::writeFile(WiiFile* file)
|
|||
atUint8* data = new atUint8[roundedSize];
|
||||
memset(data, 0, roundedSize);
|
||||
|
||||
aes_set_key(SD_KEY);
|
||||
aes_encrypt(iv, file->data(), data, roundedSize);
|
||||
std::unique_ptr<IAES> aes = NewAES();
|
||||
aes->setKey(SD_KEY);
|
||||
aes->encrypt(iv, file->data(), data, roundedSize);
|
||||
|
||||
base::writeBytes((atInt8*)data, roundedSize);
|
||||
ret += roundedSize;
|
||||
|
|
467
src/aes.c
467
src/aes.c
|
@ -1,467 +0,0 @@
|
|||
/* Rijndael Block Cipher - aes.c
|
||||
|
||||
Written by Mike Scott 21st April 1999
|
||||
mike@compapp.dcu.ie
|
||||
|
||||
Permission for free direct or derivative use is granted subject
|
||||
to compliance with any conditions that the originators of the
|
||||
algorithm place on its exploitation.
|
||||
|
||||
*/
|
||||
#include "aes.h"
|
||||
#include <stdio.h>
|
||||
//#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* rotates x one bit to the left */
|
||||
|
||||
#define ROTL(x) (((x)>>7)|((x)<<1))
|
||||
|
||||
/* Rotates 32-bit word left by 1, 2 or 3 byte */
|
||||
|
||||
#define ROTL8(x) (((x)<<8)|((x)>>24))
|
||||
#define ROTL16(x) (((x)<<16)|((x)>>16))
|
||||
#define ROTL24(x) (((x)<<24)|((x)>>8))
|
||||
|
||||
/* Fixed Data */
|
||||
|
||||
static atUint8 InCo[4] = {0xB, 0xD, 0x9, 0xE}; /* Inverse Coefficients */
|
||||
|
||||
static atUint8 fbsub[256];
|
||||
static atUint8 rbsub[256];
|
||||
static atUint8 ptab[256], ltab[256];
|
||||
static atUint32 ftable[256];
|
||||
static atUint32 rtable[256];
|
||||
static atUint32 rco[30];
|
||||
|
||||
/* Parameter-dependent data */
|
||||
|
||||
int Nk, Nb, Nr;
|
||||
atUint8 fi[24], ri[24];
|
||||
atUint32 fkey[120];
|
||||
atUint32 rkey[120];
|
||||
|
||||
static atUint32 pack(const atUint8* b)
|
||||
{
|
||||
/* pack bytes into a 32-bit Word */
|
||||
return ((atUint32)b[3] << 24) | ((atUint32)b[2] << 16) | ((atUint32)b[1] << 8) | (atUint32)b[0];
|
||||
}
|
||||
|
||||
static void unpack(atUint32 a, atUint8* b)
|
||||
{
|
||||
/* unpack bytes from a word */
|
||||
b[0] = (atUint8)a;
|
||||
b[1] = (atUint8)(a >> 8);
|
||||
b[2] = (atUint8)(a >> 16);
|
||||
b[3] = (atUint8)(a >> 24);
|
||||
}
|
||||
|
||||
static atUint8 xtime(atUint8 a)
|
||||
{
|
||||
atUint8 b;
|
||||
|
||||
if (a & 0x80) b = 0x1B;
|
||||
else b = 0;
|
||||
|
||||
a <<= 1;
|
||||
a ^= b;
|
||||
return a;
|
||||
}
|
||||
|
||||
static atUint8 bmul(atUint8 x, atUint8 y)
|
||||
{
|
||||
/* x.y= AntiLog(Log(x) + Log(y)) */
|
||||
if (x && y) return ptab[(ltab[x] + ltab[y]) % 255];
|
||||
else return 0;
|
||||
}
|
||||
|
||||
static atUint32 SubByte(atUint32 a)
|
||||
{
|
||||
atUint8 b[4];
|
||||
unpack(a, b);
|
||||
b[0] = fbsub[b[0]];
|
||||
b[1] = fbsub[b[1]];
|
||||
b[2] = fbsub[b[2]];
|
||||
b[3] = fbsub[b[3]];
|
||||
return pack(b);
|
||||
}
|
||||
|
||||
static atUint8 product(atUint32 x, atUint32 y)
|
||||
{
|
||||
/* dot product of two 4-byte arrays */
|
||||
atUint8 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 atUint32 InvMixCol(atUint32 x)
|
||||
{
|
||||
/* matrix Multiplication */
|
||||
atUint32 y, m;
|
||||
atUint8 b[4];
|
||||
|
||||
m = pack(InCo);
|
||||
b[3] = product(m, x);
|
||||
m = ROTL24(m);
|
||||
b[2] = product(m, x);
|
||||
m = ROTL24(m);
|
||||
b[1] = product(m, x);
|
||||
m = ROTL24(m);
|
||||
b[0] = product(m, x);
|
||||
y = pack(b);
|
||||
return y;
|
||||
}
|
||||
|
||||
atUint8 ByteSub(atUint8 x)
|
||||
{
|
||||
atUint8 y = ptab[255 - ltab[x]]; /* multiplicative inverse */
|
||||
x = y;
|
||||
x = ROTL(x);
|
||||
y ^= x;
|
||||
x = ROTL(x);
|
||||
y ^= x;
|
||||
x = ROTL(x);
|
||||
y ^= x;
|
||||
x = ROTL(x);
|
||||
y ^= x;
|
||||
y ^= 0x63;
|
||||
return y;
|
||||
}
|
||||
|
||||
void gentables(void)
|
||||
{
|
||||
/* generate tables */
|
||||
int i;
|
||||
atUint8 y, b[4];
|
||||
|
||||
/* use 3 as primitive root to generate power and log tables */
|
||||
|
||||
ltab[0] = 0;
|
||||
ptab[0] = 1;
|
||||
ltab[1] = 0;
|
||||
ptab[1] = 3;
|
||||
ltab[3] = 1;
|
||||
|
||||
for (i = 2; i < 256; i++)
|
||||
{
|
||||
ptab[i] = ptab[i - 1] ^ xtime(ptab[i - 1]);
|
||||
ltab[ptab[i]] = i;
|
||||
}
|
||||
|
||||
/* affine transformation:- each bit is xored with itself shifted one bit */
|
||||
|
||||
fbsub[0] = 0x63;
|
||||
rbsub[0x63] = 0;
|
||||
|
||||
for (i = 1; i < 256; i++)
|
||||
{
|
||||
y = ByteSub((atUint8)i);
|
||||
fbsub[i] = y;
|
||||
rbsub[y] = i;
|
||||
}
|
||||
|
||||
for (i = 0, y = 1; i < 30; i++)
|
||||
{
|
||||
rco[i] = y;
|
||||
y = xtime(y);
|
||||
}
|
||||
|
||||
/* calculate forward and reverse tables */
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
y = fbsub[i];
|
||||
b[3] = y ^ xtime(y);
|
||||
b[2] = y;
|
||||
b[1] = y;
|
||||
b[0] = xtime(y);
|
||||
ftable[i] = pack(b);
|
||||
|
||||
y = rbsub[i];
|
||||
b[3] = bmul(InCo[0], y);
|
||||
b[2] = bmul(InCo[1], y);
|
||||
b[1] = bmul(InCo[2], y);
|
||||
b[0] = bmul(InCo[3], y);
|
||||
rtable[i] = pack(b);
|
||||
}
|
||||
}
|
||||
|
||||
void gkey(int nb, int nk, const atUint8* 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;
|
||||
atUint32 CipherKey[8];
|
||||
|
||||
Nb = nb;
|
||||
Nk = nk;
|
||||
|
||||
/* Nr is number of rounds */
|
||||
if (Nb >= Nk) Nr = 6 + Nb;
|
||||
else Nr = 6 + Nk;
|
||||
|
||||
C1 = 1;
|
||||
|
||||
if (Nb < 8) { C2 = 2; C3 = 3; }
|
||||
else { C2 = 3; C3 = 4; }
|
||||
|
||||
/* pre-calculate forward and reverse increments */
|
||||
for (m = j = 0; j < nb; j++, m += 3)
|
||||
{
|
||||
fi[m] = (j + C1) % nb;
|
||||
fi[m + 1] = (j + C2) % nb;
|
||||
fi[m + 2] = (j + C3) % nb;
|
||||
ri[m] = (nb + j - C1) % nb;
|
||||
ri[m + 1] = (nb + j - C2) % nb;
|
||||
ri[m + 2] = (nb + j - C3) % nb;
|
||||
}
|
||||
|
||||
N = Nb * (Nr + 1);
|
||||
|
||||
for (i = j = 0; i < Nk; i++, j += 4)
|
||||
{
|
||||
CipherKey[i] = pack(key + j);
|
||||
}
|
||||
|
||||
for (i = 0; i < Nk; i++) fkey[i] = CipherKey[i];
|
||||
|
||||
for (j = Nk, k = 0; j < N; j += Nk, k++)
|
||||
{
|
||||
fkey[j] = fkey[j - Nk] ^ SubByte(ROTL24(fkey[j - 1]))^rco[k];
|
||||
|
||||
if (Nk <= 6)
|
||||
{
|
||||
for (i = 1; i < Nk && (i + j) < N; i++)
|
||||
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 1; i < 4 && (i + j) < N; i++)
|
||||
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
|
||||
|
||||
if ((j + 4) < N) fkey[j + 4] = fkey[j + 4 - Nk] ^ SubByte(fkey[j + 3]);
|
||||
|
||||
for (i = 5; i < Nk && (i + j) < N; i++)
|
||||
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* now for the expanded decrypt key in reverse order */
|
||||
|
||||
for (j = 0; j < Nb; j++) rkey[j + N - Nb] = fkey[j];
|
||||
|
||||
for (i = Nb; i < N - Nb; i += Nb)
|
||||
{
|
||||
k = N - Nb - i;
|
||||
|
||||
for (j = 0; j < Nb; j++) rkey[k + j] = InvMixCol(fkey[i + j]);
|
||||
}
|
||||
|
||||
for (j = N - Nb; j < N; j++) rkey[j - N + Nb] = fkey[j];
|
||||
}
|
||||
|
||||
|
||||
/* There is an obvious time/space trade-off possible here. *
|
||||
* Instead of just one ftable[], I could have 4, the other *
|
||||
* 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
|
||||
|
||||
void encrypt(atUint8* buff)
|
||||
{
|
||||
int i, j, k, m;
|
||||
atUint32 a[8], b[8], *x, *y, *t;
|
||||
|
||||
for (i = j = 0; i < Nb; i++, j += 4)
|
||||
{
|
||||
a[i] = pack(buff + j);
|
||||
a[i] ^= fkey[i];
|
||||
}
|
||||
|
||||
k = Nb;
|
||||
x = a;
|
||||
y = b;
|
||||
|
||||
/* State alternates between a and b */
|
||||
for (i = 1; i < Nr; i++)
|
||||
{
|
||||
/* Nr is number of rounds. May be odd. */
|
||||
|
||||
/* if Nb is fixed - unroll this next
|
||||
loop and hard-code in the values of fi[] */
|
||||
|
||||
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[(atUint8)x[j]] ^
|
||||
ROTL8(ftable[(atUint8)(x[fi[m]] >> 8)])^
|
||||
ROTL16(ftable[(atUint8)(x[fi[m + 1]] >> 16)])^
|
||||
ROTL24(ftable[(atUint8)(x[fi[m + 2]] >> 24)]);
|
||||
}
|
||||
|
||||
t = x;
|
||||
x = y;
|
||||
y = t; /* swap pointers */
|
||||
}
|
||||
|
||||
/* Last Round - unroll if possible */
|
||||
for (m = j = 0; j < Nb; j++, m += 3)
|
||||
{
|
||||
y[j] = fkey[k++] ^ (atUint32)fbsub[(atUint8)x[j]] ^
|
||||
ROTL8((atUint32)fbsub[(atUint8)(x[fi[m]] >> 8)])^
|
||||
ROTL16((atUint32)fbsub[(atUint8)(x[fi[m + 1]] >> 16)])^
|
||||
ROTL24((atUint32)fbsub[(atUint8)(x[fi[m + 2]] >> 24)]);
|
||||
}
|
||||
|
||||
for (i = j = 0; i < Nb; i++, j += 4)
|
||||
{
|
||||
unpack(y[i], (atUint8*)&buff[j]);
|
||||
x[i] = y[i] = 0; /* clean up stack */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void decrypt(atUint8* buff)
|
||||
{
|
||||
int i, j, k, m;
|
||||
atUint32 a[8], b[8], *x, *y, *t;
|
||||
|
||||
for (i = j = 0; i < Nb; i++, j += 4)
|
||||
{
|
||||
a[i] = pack(buff + j);
|
||||
a[i] ^= rkey[i];
|
||||
}
|
||||
|
||||
k = Nb;
|
||||
x = a;
|
||||
y = b;
|
||||
|
||||
/* State alternates between a and b */
|
||||
for (i = 1; i < Nr; i++)
|
||||
{
|
||||
/* Nr is number of rounds. May be odd. */
|
||||
|
||||
/* if Nb is fixed - unroll this next
|
||||
loop and hard-code in the values of ri[] */
|
||||
|
||||
for (m = j = 0; j < Nb; j++, m += 3)
|
||||
{
|
||||
/* This is the time-critical bit */
|
||||
y[j] = rkey[k++] ^ rtable[(atUint8)x[j]] ^
|
||||
ROTL8(rtable[(atUint8)(x[ri[m]] >> 8)])^
|
||||
ROTL16(rtable[(atUint8)(x[ri[m + 1]] >> 16)])^
|
||||
ROTL24(rtable[(atUint8)(x[ri[m + 2]] >> 24)]);
|
||||
}
|
||||
|
||||
t = x;
|
||||
x = y;
|
||||
y = t; /* swap pointers */
|
||||
}
|
||||
|
||||
/* Last Round - unroll if possible */
|
||||
for (m = j = 0; j < Nb; j++, m += 3)
|
||||
{
|
||||
y[j] = rkey[k++] ^ (atUint32)rbsub[(atUint8)x[j]] ^
|
||||
ROTL8((atUint32)rbsub[(atUint8)(x[ri[m]] >> 8)])^
|
||||
ROTL16((atUint32)rbsub[(atUint8)(x[ri[m + 1]] >> 16)])^
|
||||
ROTL24((atUint32)rbsub[(atUint8)(x[ri[m + 2]] >> 24)]);
|
||||
}
|
||||
|
||||
for (i = j = 0; i < Nb; i++, j += 4)
|
||||
{
|
||||
unpack(y[i], (atUint8*)&buff[j]);
|
||||
x[i] = y[i] = 0; /* clean up stack */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void aes_set_key(const atUint8* key)
|
||||
{
|
||||
gentables();
|
||||
gkey(4, 4, key);
|
||||
}
|
||||
|
||||
// CBC mode decryption
|
||||
void aes_decrypt(atUint8* iv, const atUint8* inbuf, atUint8* outbuf, atUint64 len)
|
||||
{
|
||||
atUint8 block[16];
|
||||
atUint8* ctext_ptr;
|
||||
unsigned int blockno = 0, i;
|
||||
|
||||
//fprintf( stderr,"aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len );
|
||||
//printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
|
||||
|
||||
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++)
|
||||
{
|
||||
unsigned int fraction;
|
||||
|
||||
if (blockno == (len / sizeof(block))) // last block
|
||||
{
|
||||
fraction = len % sizeof(block);
|
||||
|
||||
if (fraction == 0) break;
|
||||
|
||||
memset(block, 0, sizeof(block));
|
||||
}
|
||||
else fraction = 16;
|
||||
|
||||
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
|
||||
memcpy(block, inbuf + blockno * sizeof(block), fraction);
|
||||
decrypt(block);
|
||||
|
||||
if (blockno == 0) ctext_ptr = iv;
|
||||
else ctext_ptr = (atUint8*)(inbuf + (blockno - 1) * sizeof(block));
|
||||
|
||||
for (i = 0; i < fraction; i++)
|
||||
outbuf[blockno * sizeof(block) + i] =
|
||||
ctext_ptr[i] ^ block[i];
|
||||
|
||||
// debug_printf("Block %d output: ", blockno);
|
||||
// hexdump(outbuf + blockno*sizeof(block), 16);
|
||||
}
|
||||
}
|
||||
|
||||
// CBC mode encryption
|
||||
void aes_encrypt(atUint8* iv, const atUint8* inbuf, atUint8* outbuf, atUint64 len)
|
||||
{
|
||||
atUint8 block[16];
|
||||
unsigned int blockno = 0, i;
|
||||
|
||||
//printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
|
||||
//fprintf( stderr,"aes_encrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
|
||||
|
||||
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++)
|
||||
{
|
||||
unsigned int fraction;
|
||||
|
||||
if (blockno == (len / sizeof(block))) // last block
|
||||
{
|
||||
fraction = len % sizeof(block);
|
||||
|
||||
if (fraction == 0) break;
|
||||
|
||||
memset(block, 0, sizeof(block));
|
||||
}
|
||||
else fraction = 16;
|
||||
|
||||
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
|
||||
memcpy(block, inbuf + blockno * sizeof(block), fraction);
|
||||
|
||||
for (i = 0; i < fraction; i++)
|
||||
block[i] = inbuf[blockno * sizeof(block) + i] ^ iv[i];
|
||||
|
||||
encrypt(block);
|
||||
memcpy(iv, block, sizeof(block));
|
||||
memcpy(outbuf + blockno * sizeof(block), block, sizeof(block));
|
||||
// debug_printf("Block %d output: ", blockno);
|
||||
// hexdump(outbuf + blockno*sizeof(block), 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,618 @@
|
|||
#include "aes.hpp"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cpuid.h>
|
||||
|
||||
namespace Athena
|
||||
{
|
||||
|
||||
/* rotates x one bit to the left */
|
||||
|
||||
#define ROTL(x) (((x)>>7)|((x)<<1))
|
||||
|
||||
/* Rotates 32-bit word left by 1, 2 or 3 byte */
|
||||
|
||||
#define ROTL8(x) (((x)<<8)|((x)>>24))
|
||||
#define ROTL16(x) (((x)<<16)|((x)>>16))
|
||||
#define ROTL24(x) (((x)<<24)|((x)>>8))
|
||||
|
||||
/* Fixed Data */
|
||||
|
||||
static const uint8_t InCo[4] = {0xB, 0xD, 0x9, 0xE}; /* Inverse Coefficients */
|
||||
|
||||
static inline uint32_t pack(const uint8_t* b)
|
||||
{
|
||||
/* pack bytes into a 32-bit Word */
|
||||
return ((uint32_t)b[3] << 24) | ((uint32_t)b[2] << 16) | ((uint32_t)b[1] << 8) | (uint32_t)b[0];
|
||||
}
|
||||
|
||||
static inline void unpack(uint32_t a, uint8_t* b)
|
||||
{
|
||||
/* unpack bytes from a word */
|
||||
b[0] = (uint8_t)a;
|
||||
b[1] = (uint8_t)(a >> 8);
|
||||
b[2] = (uint8_t)(a >> 16);
|
||||
b[3] = (uint8_t)(a >> 24);
|
||||
}
|
||||
|
||||
static inline uint8_t xtime(uint8_t a)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
if (a & 0x80) b = 0x1B;
|
||||
else b = 0;
|
||||
|
||||
a <<= 1;
|
||||
a ^= b;
|
||||
return a;
|
||||
}
|
||||
|
||||
class SoftwareAES : public IAES
|
||||
{
|
||||
protected:
|
||||
uint8_t fbsub[256];
|
||||
uint8_t rbsub[256];
|
||||
uint8_t ptab[256], ltab[256];
|
||||
uint32_t ftable[256];
|
||||
uint32_t rtable[256];
|
||||
uint32_t rco[30];
|
||||
|
||||
/* Parameter-dependent data */
|
||||
|
||||
int Nk, Nb, Nr;
|
||||
uint8_t fi[24], ri[24];
|
||||
uint32_t fkey[120];
|
||||
uint32_t rkey[120];
|
||||
|
||||
|
||||
uint8_t bmul(uint8_t x, uint8_t y);
|
||||
uint32_t SubByte(uint32_t a);
|
||||
uint8_t product(uint32_t x, uint32_t y);
|
||||
uint32_t InvMixCol(uint32_t x);
|
||||
uint8_t ByteSub(uint8_t x);
|
||||
void gentables(void);
|
||||
void gkey(int nb, int nk, const uint8_t* key);
|
||||
void _encrypt(uint8_t* buff);
|
||||
void _decrypt(uint8_t* buff);
|
||||
|
||||
public:
|
||||
void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len);
|
||||
void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len);
|
||||
void setKey(const uint8_t* key);
|
||||
};
|
||||
|
||||
uint8_t SoftwareAES::bmul(uint8_t x, uint8_t y)
|
||||
{
|
||||
/* x.y= AntiLog(Log(x) + Log(y)) */
|
||||
if (x && y) return ptab[(ltab[x] + ltab[y]) % 255];
|
||||
else return 0;
|
||||
}
|
||||
|
||||
uint32_t SoftwareAES::SubByte(uint32_t a)
|
||||
{
|
||||
uint8_t b[4];
|
||||
unpack(a, b);
|
||||
b[0] = fbsub[b[0]];
|
||||
b[1] = fbsub[b[1]];
|
||||
b[2] = fbsub[b[2]];
|
||||
b[3] = fbsub[b[3]];
|
||||
return pack(b);
|
||||
}
|
||||
|
||||
uint8_t SoftwareAES::product(uint32_t x, uint32_t y)
|
||||
{
|
||||
/* dot product of two 4-byte arrays */
|
||||
uint8_t 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]);
|
||||
}
|
||||
|
||||
uint32_t SoftwareAES::InvMixCol(uint32_t x)
|
||||
{
|
||||
/* matrix Multiplication */
|
||||
uint32_t y, m;
|
||||
uint8_t b[4];
|
||||
|
||||
m = pack(InCo);
|
||||
b[3] = product(m, x);
|
||||
m = ROTL24(m);
|
||||
b[2] = product(m, x);
|
||||
m = ROTL24(m);
|
||||
b[1] = product(m, x);
|
||||
m = ROTL24(m);
|
||||
b[0] = product(m, x);
|
||||
y = pack(b);
|
||||
return y;
|
||||
}
|
||||
|
||||
uint8_t SoftwareAES::ByteSub(uint8_t x)
|
||||
{
|
||||
uint8_t y = ptab[255 - ltab[x]]; /* multiplicative inverse */
|
||||
x = y;
|
||||
x = ROTL(x);
|
||||
y ^= x;
|
||||
x = ROTL(x);
|
||||
y ^= x;
|
||||
x = ROTL(x);
|
||||
y ^= x;
|
||||
x = ROTL(x);
|
||||
y ^= x;
|
||||
y ^= 0x63;
|
||||
return y;
|
||||
}
|
||||
|
||||
void SoftwareAES::gentables(void)
|
||||
{
|
||||
/* generate tables */
|
||||
int i;
|
||||
uint8_t y, b[4];
|
||||
|
||||
/* use 3 as primitive root to generate power and log tables */
|
||||
|
||||
ltab[0] = 0;
|
||||
ptab[0] = 1;
|
||||
ltab[1] = 0;
|
||||
ptab[1] = 3;
|
||||
ltab[3] = 1;
|
||||
|
||||
for (i = 2; i < 256; i++)
|
||||
{
|
||||
ptab[i] = ptab[i - 1] ^ xtime(ptab[i - 1]);
|
||||
ltab[ptab[i]] = i;
|
||||
}
|
||||
|
||||
/* affine transformation:- each bit is xored with itself shifted one bit */
|
||||
|
||||
fbsub[0] = 0x63;
|
||||
rbsub[0x63] = 0;
|
||||
|
||||
for (i = 1; i < 256; i++)
|
||||
{
|
||||
y = ByteSub((uint8_t)i);
|
||||
fbsub[i] = y;
|
||||
rbsub[y] = i;
|
||||
}
|
||||
|
||||
for (i = 0, y = 1; i < 30; i++)
|
||||
{
|
||||
rco[i] = y;
|
||||
y = xtime(y);
|
||||
}
|
||||
|
||||
/* calculate forward and reverse tables */
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
y = fbsub[i];
|
||||
b[3] = y ^ xtime(y);
|
||||
b[2] = y;
|
||||
b[1] = y;
|
||||
b[0] = xtime(y);
|
||||
ftable[i] = pack(b);
|
||||
|
||||
y = rbsub[i];
|
||||
b[3] = bmul(InCo[0], y);
|
||||
b[2] = bmul(InCo[1], y);
|
||||
b[1] = bmul(InCo[2], y);
|
||||
b[0] = bmul(InCo[3], y);
|
||||
rtable[i] = pack(b);
|
||||
}
|
||||
}
|
||||
|
||||
void SoftwareAES::gkey(int nb, int nk, const uint8_t* 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;
|
||||
uint32_t CipherKey[8];
|
||||
|
||||
Nb = nb;
|
||||
Nk = nk;
|
||||
|
||||
/* Nr is number of rounds */
|
||||
if (Nb >= Nk) Nr = 6 + Nb;
|
||||
else Nr = 6 + Nk;
|
||||
|
||||
C1 = 1;
|
||||
|
||||
if (Nb < 8) { C2 = 2; C3 = 3; }
|
||||
else { C2 = 3; C3 = 4; }
|
||||
|
||||
/* pre-calculate forward and reverse increments */
|
||||
for (m = j = 0; j < nb; j++, m += 3)
|
||||
{
|
||||
fi[m] = (j + C1) % nb;
|
||||
fi[m + 1] = (j + C2) % nb;
|
||||
fi[m + 2] = (j + C3) % nb;
|
||||
ri[m] = (nb + j - C1) % nb;
|
||||
ri[m + 1] = (nb + j - C2) % nb;
|
||||
ri[m + 2] = (nb + j - C3) % nb;
|
||||
}
|
||||
|
||||
N = Nb * (Nr + 1);
|
||||
|
||||
for (i = j = 0; i < Nk; i++, j += 4)
|
||||
{
|
||||
CipherKey[i] = pack(key + j);
|
||||
}
|
||||
|
||||
for (i = 0; i < Nk; i++) fkey[i] = CipherKey[i];
|
||||
|
||||
for (j = Nk, k = 0; j < N; j += Nk, k++)
|
||||
{
|
||||
fkey[j] = fkey[j - Nk] ^ SubByte(ROTL24(fkey[j - 1]))^rco[k];
|
||||
|
||||
if (Nk <= 6)
|
||||
{
|
||||
for (i = 1; i < Nk && (i + j) < N; i++)
|
||||
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 1; i < 4 && (i + j) < N; i++)
|
||||
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
|
||||
|
||||
if ((j + 4) < N) fkey[j + 4] = fkey[j + 4 - Nk] ^ SubByte(fkey[j + 3]);
|
||||
|
||||
for (i = 5; i < Nk && (i + j) < N; i++)
|
||||
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* now for the expanded decrypt key in reverse order */
|
||||
|
||||
for (j = 0; j < Nb; j++) rkey[j + N - Nb] = fkey[j];
|
||||
|
||||
for (i = Nb; i < N - Nb; i += Nb)
|
||||
{
|
||||
k = N - Nb - i;
|
||||
|
||||
for (j = 0; j < Nb; j++) rkey[k + j] = InvMixCol(fkey[i + j]);
|
||||
}
|
||||
|
||||
for (j = N - Nb; j < N; j++) rkey[j - N + Nb] = fkey[j];
|
||||
}
|
||||
|
||||
|
||||
/* There is an obvious time/space trade-off possible here. *
|
||||
* Instead of just one ftable[], I could have 4, the other *
|
||||
* 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
|
||||
|
||||
void SoftwareAES::_encrypt(uint8_t* buff)
|
||||
{
|
||||
int i, j, k, m;
|
||||
uint32_t a[8], b[8], *x, *y, *t;
|
||||
|
||||
for (i = j = 0; i < Nb; i++, j += 4)
|
||||
{
|
||||
a[i] = pack(buff + j);
|
||||
a[i] ^= fkey[i];
|
||||
}
|
||||
|
||||
k = Nb;
|
||||
x = a;
|
||||
y = b;
|
||||
|
||||
/* State alternates between a and b */
|
||||
for (i = 1; i < Nr; i++)
|
||||
{
|
||||
/* Nr is number of rounds. May be odd. */
|
||||
|
||||
/* if Nb is fixed - unroll this next
|
||||
loop and hard-code in the values of fi[] */
|
||||
|
||||
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[(uint8_t)x[j]] ^
|
||||
ROTL8(ftable[(uint8_t)(x[fi[m]] >> 8)])^
|
||||
ROTL16(ftable[(uint8_t)(x[fi[m + 1]] >> 16)])^
|
||||
ROTL24(ftable[(uint8_t)(x[fi[m + 2]] >> 24)]);
|
||||
}
|
||||
|
||||
t = x;
|
||||
x = y;
|
||||
y = t; /* swap pointers */
|
||||
}
|
||||
|
||||
/* Last Round - unroll if possible */
|
||||
for (m = j = 0; j < Nb; j++, m += 3)
|
||||
{
|
||||
y[j] = fkey[k++] ^ (uint32_t)fbsub[(uint8_t)x[j]] ^
|
||||
ROTL8((uint32_t)fbsub[(uint8_t)(x[fi[m]] >> 8)])^
|
||||
ROTL16((uint32_t)fbsub[(uint8_t)(x[fi[m + 1]] >> 16)])^
|
||||
ROTL24((uint32_t)fbsub[(uint8_t)(x[fi[m + 2]] >> 24)]);
|
||||
}
|
||||
|
||||
for (i = j = 0; i < Nb; i++, j += 4)
|
||||
{
|
||||
unpack(y[i], (uint8_t*)&buff[j]);
|
||||
x[i] = y[i] = 0; /* clean up stack */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SoftwareAES::_decrypt(uint8_t* buff)
|
||||
{
|
||||
int i, j, k, m;
|
||||
uint32_t a[8], b[8], *x, *y, *t;
|
||||
|
||||
for (i = j = 0; i < Nb; i++, j += 4)
|
||||
{
|
||||
a[i] = pack(buff + j);
|
||||
a[i] ^= rkey[i];
|
||||
}
|
||||
|
||||
k = Nb;
|
||||
x = a;
|
||||
y = b;
|
||||
|
||||
/* State alternates between a and b */
|
||||
for (i = 1; i < Nr; i++)
|
||||
{
|
||||
/* Nr is number of rounds. May be odd. */
|
||||
|
||||
/* if Nb is fixed - unroll this next
|
||||
loop and hard-code in the values of ri[] */
|
||||
|
||||
for (m = j = 0; j < Nb; j++, m += 3)
|
||||
{
|
||||
/* This is the time-critical bit */
|
||||
y[j] = rkey[k++] ^ rtable[(uint8_t)x[j]] ^
|
||||
ROTL8(rtable[(uint8_t)(x[ri[m]] >> 8)])^
|
||||
ROTL16(rtable[(uint8_t)(x[ri[m + 1]] >> 16)])^
|
||||
ROTL24(rtable[(uint8_t)(x[ri[m + 2]] >> 24)]);
|
||||
}
|
||||
|
||||
t = x;
|
||||
x = y;
|
||||
y = t; /* swap pointers */
|
||||
}
|
||||
|
||||
/* Last Round - unroll if possible */
|
||||
for (m = j = 0; j < Nb; j++, m += 3)
|
||||
{
|
||||
y[j] = rkey[k++] ^ (uint32_t)rbsub[(uint8_t)x[j]] ^
|
||||
ROTL8((uint32_t)rbsub[(uint8_t)(x[ri[m]] >> 8)])^
|
||||
ROTL16((uint32_t)rbsub[(uint8_t)(x[ri[m + 1]] >> 16)])^
|
||||
ROTL24((uint32_t)rbsub[(uint8_t)(x[ri[m + 2]] >> 24)]);
|
||||
}
|
||||
|
||||
for (i = j = 0; i < Nb; i++, j += 4)
|
||||
{
|
||||
unpack(y[i], (uint8_t*)&buff[j]);
|
||||
x[i] = y[i] = 0; /* clean up stack */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SoftwareAES::setKey(const uint8_t* key)
|
||||
{
|
||||
gentables();
|
||||
gkey(4, 4, key);
|
||||
}
|
||||
|
||||
// CBC mode decryption
|
||||
void SoftwareAES::decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len)
|
||||
{
|
||||
uint8_t block[16];
|
||||
const uint8_t* ctext_ptr;
|
||||
unsigned int blockno = 0, i;
|
||||
|
||||
//fprintf( stderr,"aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len );
|
||||
//printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
|
||||
|
||||
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++)
|
||||
{
|
||||
unsigned int fraction;
|
||||
|
||||
if (blockno == (len / sizeof(block))) // last block
|
||||
{
|
||||
fraction = len % sizeof(block);
|
||||
|
||||
if (fraction == 0) break;
|
||||
|
||||
memset(block, 0, sizeof(block));
|
||||
}
|
||||
else fraction = 16;
|
||||
|
||||
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
|
||||
memcpy(block, inbuf + blockno * sizeof(block), fraction);
|
||||
_decrypt(block);
|
||||
|
||||
if (blockno == 0) ctext_ptr = iv;
|
||||
else ctext_ptr = (uint8_t*)(inbuf + (blockno - 1) * sizeof(block));
|
||||
|
||||
for (i = 0; i < fraction; i++)
|
||||
outbuf[blockno * sizeof(block) + i] =
|
||||
ctext_ptr[i] ^ block[i];
|
||||
|
||||
// debug_printf("Block %d output: ", blockno);
|
||||
// hexdump(outbuf + blockno*sizeof(block), 16);
|
||||
}
|
||||
}
|
||||
|
||||
// CBC mode encryption
|
||||
void SoftwareAES::encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)
|
||||
{
|
||||
uint8_t block[16];
|
||||
uint8_t feedback[16];
|
||||
memcpy(feedback, iv, 16);
|
||||
unsigned int blockno = 0, i;
|
||||
|
||||
//printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
|
||||
//fprintf( stderr,"aes_encrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
|
||||
|
||||
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++)
|
||||
{
|
||||
unsigned int fraction;
|
||||
|
||||
if (blockno == (len / sizeof(block))) // last block
|
||||
{
|
||||
fraction = len % sizeof(block);
|
||||
|
||||
if (fraction == 0) break;
|
||||
|
||||
memset(block, 0, sizeof(block));
|
||||
}
|
||||
else fraction = 16;
|
||||
|
||||
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
|
||||
memcpy(block, inbuf + blockno * sizeof(block), fraction);
|
||||
|
||||
for (i = 0; i < fraction; i++)
|
||||
block[i] = inbuf[blockno * sizeof(block) + i] ^ feedback[i];
|
||||
|
||||
_encrypt(block);
|
||||
memcpy(feedback, block, sizeof(block));
|
||||
memcpy(outbuf + blockno * sizeof(block), block, sizeof(block));
|
||||
// debug_printf("Block %d output: ", blockno);
|
||||
// hexdump(outbuf + blockno*sizeof(block), 16);
|
||||
}
|
||||
}
|
||||
|
||||
#if __AES__
|
||||
|
||||
#include <wmmintrin.h>
|
||||
|
||||
class NiAES : public IAES
|
||||
{
|
||||
__m128i m_ekey[11];
|
||||
__m128i m_dkey[11];
|
||||
public:
|
||||
void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)
|
||||
{
|
||||
__m128i feedback,data;
|
||||
uint64_t i,j;
|
||||
if (len%16)
|
||||
len = len/16+1;
|
||||
else
|
||||
len /= 16;
|
||||
feedback = _mm_loadu_si128((__m128i*)iv);
|
||||
for (i=0 ; i<len ; i++)
|
||||
{
|
||||
data = _mm_loadu_si128(&((__m128i*)inbuf)[i]);
|
||||
feedback = _mm_xor_si128(data, feedback);
|
||||
feedback = _mm_xor_si128(feedback, m_ekey[0]);
|
||||
for (j=1 ; j<10 ; j++)
|
||||
feedback = _mm_aesenc_si128(feedback, m_ekey[j]);
|
||||
feedback = _mm_aesenclast_si128(feedback, m_ekey[j]);
|
||||
_mm_storeu_si128(&((__m128i*)outbuf)[i], feedback);
|
||||
}
|
||||
}
|
||||
void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)
|
||||
{
|
||||
__m128i data,feedback,last_in;
|
||||
uint64_t i,j;
|
||||
if (len%16)
|
||||
len = len/16+1;
|
||||
else
|
||||
len /= 16;
|
||||
feedback = _mm_loadu_si128((__m128i*)iv);
|
||||
for (i=0 ; i<len ; i++)
|
||||
{
|
||||
last_in=_mm_loadu_si128(&((__m128i*)inbuf)[i]);
|
||||
data = _mm_xor_si128(last_in, m_dkey[0]);
|
||||
for (j=1 ; j<10 ; j++)
|
||||
data = _mm_aesdec_si128(data, m_dkey[j]);
|
||||
data = _mm_aesdeclast_si128(data, m_dkey[j]);
|
||||
data = _mm_xor_si128(data, feedback);
|
||||
_mm_storeu_si128(&((__m128i*)outbuf)[i], data);
|
||||
feedback = last_in;
|
||||
}
|
||||
}
|
||||
|
||||
static inline __m128i AES_128_ASSIST (__m128i temp1, __m128i temp2)
|
||||
{
|
||||
__m128i temp3;
|
||||
temp2 = _mm_shuffle_epi32 (temp2 ,0xff);
|
||||
temp3 = _mm_slli_si128 (temp1, 0x4);
|
||||
temp1 = _mm_xor_si128 (temp1, temp3);
|
||||
temp3 = _mm_slli_si128 (temp3, 0x4);
|
||||
temp1 = _mm_xor_si128 (temp1, temp3);
|
||||
temp3 = _mm_slli_si128 (temp3, 0x4);
|
||||
temp1 = _mm_xor_si128 (temp1, temp3);
|
||||
temp1 = _mm_xor_si128 (temp1, temp2);
|
||||
return temp1;
|
||||
}
|
||||
|
||||
void setKey(const uint8_t* key)
|
||||
{
|
||||
__m128i temp1, temp2;
|
||||
|
||||
temp1 = _mm_loadu_si128((__m128i*)key);
|
||||
m_ekey[0] = temp1;
|
||||
m_dkey[10] = temp1;
|
||||
temp2 = _mm_aeskeygenassist_si128(temp1, 0x1);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
m_ekey[1] = temp1;
|
||||
m_dkey[9] = _mm_aesimc_si128(temp1);
|
||||
temp2 = _mm_aeskeygenassist_si128(temp1, 0x2);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
m_ekey[2] = temp1;
|
||||
m_dkey[8] = _mm_aesimc_si128(temp1);
|
||||
temp2 = _mm_aeskeygenassist_si128(temp1, 0x4);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
m_ekey[3] = temp1;
|
||||
m_dkey[7] = _mm_aesimc_si128(temp1);
|
||||
temp2 = _mm_aeskeygenassist_si128(temp1, 0x8);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
m_ekey[4] = temp1;
|
||||
m_dkey[6] = _mm_aesimc_si128(temp1);
|
||||
temp2 = _mm_aeskeygenassist_si128(temp1, 0x10);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
m_ekey[5] = temp1;
|
||||
m_dkey[5] = _mm_aesimc_si128(temp1);
|
||||
temp2 = _mm_aeskeygenassist_si128(temp1, 0x20);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
m_ekey[6] = temp1;
|
||||
m_dkey[4] = _mm_aesimc_si128(temp1);
|
||||
temp2 = _mm_aeskeygenassist_si128(temp1, 0x40);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
m_ekey[7] = temp1;
|
||||
m_dkey[3] = _mm_aesimc_si128(temp1);
|
||||
temp2 = _mm_aeskeygenassist_si128(temp1, 0x80);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
m_ekey[8] = temp1;
|
||||
m_dkey[2] = _mm_aesimc_si128(temp1);
|
||||
temp2 = _mm_aeskeygenassist_si128(temp1, 0x1b);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
m_ekey[9] = temp1;
|
||||
m_dkey[1] = _mm_aesimc_si128(temp1);
|
||||
temp2 = _mm_aeskeygenassist_si128(temp1, 0x36);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
m_ekey[10] = temp1;
|
||||
m_dkey[0] = temp1;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static int HAS_AES_NI = -1;
|
||||
std::unique_ptr<IAES> NewAES()
|
||||
{
|
||||
#if __AES__
|
||||
if (HAS_AES_NI == -1)
|
||||
{
|
||||
unsigned int a,b,c,d;
|
||||
__cpuid(1, a,b,c,d);
|
||||
HAS_AES_NI = ((c & 0x2000000) != 0);
|
||||
}
|
||||
if (HAS_AES_NI)
|
||||
return std::unique_ptr<IAES>(new NiAES);
|
||||
else
|
||||
return std::unique_ptr<IAES>(new SoftwareAES);
|
||||
#else
|
||||
return std::unique_ptr<IAES>(new SoftwareAES);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue