New code style refactor

This commit is contained in:
Jack Andersen 2018-12-07 19:18:17 -10:00
parent e1b29fda7a
commit 7243c687a8
123 changed files with 15125 additions and 18399 deletions

View File

@ -5,54 +5,51 @@
#include <wiiuse/wpad.h> #include <wiiuse/wpad.h>
#endif #endif
static void *xfb = nullptr; static void* xfb = nullptr;
static GXRModeObj* rmode = nullptr; static GXRModeObj* rmode = nullptr;
#endif #endif
#include <athena/MemoryReader.hpp> #include <athena/MemoryReader.hpp>
int main() int main() {
{
#if GEKKO #if GEKKO
VIDEO_Init(); VIDEO_Init();
#if HW_RVL #if HW_RVL
WPAD_Init(); WPAD_Init();
#endif #endif
PAD_Init(); PAD_Init();
rmode = VIDEO_GetPreferredMode(nullptr); rmode = VIDEO_GetPreferredMode(nullptr);
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
CON_Init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ); CON_Init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ);
CON_EnableGecko(CARD_SLOTB, true); CON_EnableGecko(CARD_SLOTB, true);
VIDEO_Configure(rmode); VIDEO_Configure(rmode);
VIDEO_SetBlack(false); VIDEO_SetBlack(false);
VIDEO_Flush(); VIDEO_Flush();
VIDEO_WaitVSync();
if (rmode->viTVMode & VI_NON_INTERLACE)
VIDEO_WaitVSync(); VIDEO_WaitVSync();
if (rmode->viTVMode & VI_NON_INTERLACE)
VIDEO_WaitVSync();
athena::io::MemoryCopyReader test("sd:/test.dat"); athena::io::MemoryCopyReader test("sd:/test.dat");
while(true) while (true) {
{
#if HW_RVL #if HW_RVL
WPAD_ScanPads(); WPAD_ScanPads();
#endif #endif
PAD_ScanPads(); PAD_ScanPads();
if (PAD_ButtonsDown(0) & PAD_BUTTON_START) if (PAD_ButtonsDown(0) & PAD_BUTTON_START)
break; break;
#if HW_RVL #if HW_RVL
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
break; break;
#endif #endif
VIDEO_WaitVSync(); VIDEO_WaitVSync();
} }
#endif #endif
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@ -3,22 +3,21 @@
#define EXPECTED_BYTES 281 #define EXPECTED_BYTES 281
int main(int argc, const char** argv) int main(int argc, const char** argv) {
{ TESTFile<atUint32, 2> file = {};
TESTFile<atUint32, 2> file = {}; file.arrCount[0] = 2;
file.arrCount[0] = 2; file.array.push_back(42);
file.array.push_back(42); file.array.push_back(64);
file.array.push_back(64); size_t binSize = 0;
size_t binSize = 0; file.binarySize(binSize);
file.binarySize(binSize); athena::io::MemoryCopyWriter w(nullptr, binSize);
athena::io::MemoryCopyWriter w(nullptr, binSize); atInt64 pos = w.position();
atInt64 pos = w.position(); file.write(w);
file.write(w); bool pass = !w.hasError() && w.position() - pos == binSize && binSize == EXPECTED_BYTES;
bool pass = !w.hasError() && w.position() - pos == binSize && binSize == EXPECTED_BYTES; if (pass)
if (pass) printf("[PASS] %" PRISize " bytes written\n", size_t(w.position() - pos));
printf("[PASS] %" PRISize " bytes written\n", size_t(w.position() - pos)); else
else printf("[FAIL] %" PRISize " bytes written; %" PRISize " bytes sized; %d bytes expected\n",
printf("[FAIL] %" PRISize " bytes written; %" PRISize " bytes sized; %d bytes expected\n", size_t(w.position() - pos), binSize, EXPECTED_BYTES);
size_t(w.position() - pos), binSize, EXPECTED_BYTES); return pass ? 0 : 1;
return pass ? 0 : 1;
} }

View File

@ -3,87 +3,71 @@
using namespace athena; using namespace athena;
typedef io::DNA<Big> BigDNA; typedef io::DNA<Big> BigDNA;
enum ETest : atUint8 enum ETest : atUint8 { ZERO, ONE, TWO, THREE };
{
ZERO,
ONE,
TWO,
THREE
};
template <ETest EVal> template <ETest EVal>
struct AT_SPECIALIZE_PARMS(ETest::ZERO, ETest::ONE, ETest::TWO, ETest::THREE) struct AT_SPECIALIZE_PARMS(ETest::ZERO, ETest::ONE, ETest::TWO, ETest::THREE) TESTSubFile : public BigDNA {
TESTSubFile : public BigDNA AT_DECL_DNA
{ Value<ETest> varE = EVal;
AT_DECL_DNA Value<atUint32> sub1;
Value<ETest> varE = EVal; Value<atUint32> sub2;
Value<atUint32> sub1;
Value<atUint32> sub2;
}; };
struct TESTSubClassFile : public TESTSubFile<ETest::ONE> struct TESTSubClassFile : public TESTSubFile<ETest::ONE> {
{ AT_DECL_DNA
AT_DECL_DNA Value<atUint32> sub3;
Value<atUint32> sub3; Value<atUint16> sub4;
Value<atUint16> sub4;
}; };
struct TESTSubSubClassFile : public TESTSubClassFile struct TESTSubSubClassFile : public TESTSubClassFile {
{ AT_DECL_DNA
AT_DECL_DNA Value<atUint32> sub5;
Value<atUint32> sub5; Value<atUint32> sub6;
Value<atUint32> sub6;
}; };
template <class Var32Tp, int Var32Val> template <class Var32Tp, int Var32Val>
struct AT_SPECIALIZE_PARMS(atUint16, 42, atUint32, 87, atUint32, 2) struct AT_SPECIALIZE_PARMS(atUint16, 42, atUint32, 87, atUint32, 2) TESTFile : public BigDNA {
TESTFile : public BigDNA AT_DECL_DNA
{ Value<bool> varBool;
AT_OVERRIDE_RCRC32(12345678) Value<Var32Tp> x4_var32 = Var32Val;
AT_OVERRIDE_RCRC32(deadbabe) Value<atUint16> x8_var16;
Value<atVec3f> vec3;
Value<atVec4f> vec4;
struct TESTNestedSubFile : public BigDNA {
AT_DECL_DNA AT_DECL_DNA
Value<bool> varBool; Value<atUint32> nestSub1;
AT_OVERRIDE_RCRC32(12345678) Value<Var32Tp> x4_var32 = Var32Val; Value<atUint32> nestSub2;
AT_OVERRIDE_RCRC32(deadbabe) Value<atUint16> x8_var16; } nestedSubFile;
Value<atVec3f> vec3;
Value<atVec4f> vec4;
struct TESTNestedSubFile : public BigDNA using TESTSubFileUsing = TESTSubFile<ETest::TWO>;
{ TESTSubFileUsing subFile;
AT_DECL_DNA
Value<atUint32> nestSub1;
Value<atUint32> nestSub2;
} nestedSubFile;
using TESTSubFileUsing = TESTSubFile<ETest::TWO>; Align<4> align;
TESTSubFileUsing subFile;
Align<4> align; template <class NestedTp, int NestedVal>
struct AT_SPECIALIZE_PARMS(atInt32, 36, atInt64, 96) TESTTemplateSubFile : public BigDNA {
AT_DECL_DNA
Value<NestedTp> explSub1 = NestedVal;
Value<Var32Tp> explSub2 = Var32Val;
};
Value<TESTTemplateSubFile<atInt32, 36>> nestedTemplate1;
Value<TESTTemplateSubFile<atInt64, 96>> nestedTemplate2;
template <class NestedTp, int NestedVal> Value<atUint32, Little> arrCount[2];
struct AT_SPECIALIZE_PARMS(atInt32, 36, atInt64, 96) Vector<atUint32, AT_DNA_COUNT(arrCount[0])> array;
TESTTemplateSubFile : public BigDNA
{
AT_DECL_DNA
Value<NestedTp> explSub1 = NestedVal;
Value<Var32Tp> explSub2 = Var32Val;
};
Value<TESTTemplateSubFile<atInt32, 36>> nestedTemplate1;
Value<TESTTemplateSubFile<atInt64, 96>> nestedTemplate2;
Value<atUint32, Little> arrCount[2]; Value<atUint32> arrAltCount;
Vector<atUint32, AT_DNA_COUNT(arrCount[0])> array; Vector<atUint32, AT_DNA_COUNT(arrAltCount)> arrayAlt;
Value<atUint32> arrAltCount; Seek<21, Current> seek;
Vector<atUint32, AT_DNA_COUNT(arrAltCount)> arrayAlt;
Seek<21, Current> seek; Value<atUint32> arrCount2;
Vector<TESTSubFile<ETest::ZERO>, AT_DNA_COUNT(arrCount[1] + arrCount2)> array2;
Value<atUint32> arrCount2; Value<atUint32> bufSz;
Vector<TESTSubFile<ETest::ZERO>, AT_DNA_COUNT(arrCount[1] + arrCount2)> array2; Buffer<AT_DNA_COUNT(bufSz)> buf;
Value<atUint32> bufSz; String<32> str;
Buffer<AT_DNA_COUNT(bufSz)> buf; WString<64> wstr;
String<32> str;
WString<64> wstr;
}; };

View File

@ -3,40 +3,38 @@
#include <string> #include <string>
#include "LZ77/LZLookupTable.hpp" #include "LZ77/LZLookupTable.hpp"
class LZBase class LZBase {
{
public: public:
explicit LZBase(atInt32 minimumOffset = 1, atInt32 slidingWindow = 4096, atInt32 minimumMatch = 3, atInt32 blockSize = 8); explicit LZBase(atInt32 minimumOffset = 1, atInt32 slidingWindow = 4096, atInt32 minimumMatch = 3,
virtual ~LZBase() {} atInt32 blockSize = 8);
virtual ~LZBase() {}
virtual atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0; virtual atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0;
virtual atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0; virtual atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0;
void setSlidingWindow(atInt32 SlidingWindow);
atInt32 slidingWindow();
void setReadAheadBuffer(atInt32 ReadAheadBuffer);
atInt32 readAheadBuffer();
void setMinMatch(atInt32 minimumMatch);
atInt32 minMatch();
void setBlockSize(atInt32 BlockSize);
atInt32 blockSize();
void setMinimumOffset(atUint32 minimumOffset);
atUint32 minimumOffset();
void setSlidingWindow(atInt32 SlidingWindow);
atInt32 slidingWindow();
void setReadAheadBuffer(atInt32 ReadAheadBuffer);
atInt32 readAheadBuffer();
void setMinMatch(atInt32 minimumMatch);
atInt32 minMatch();
void setBlockSize(atInt32 BlockSize);
atInt32 blockSize();
void setMinimumOffset(atUint32 minimumOffset);
atUint32 minimumOffset();
private: private:
atInt32 subMatch(const atUint8* str1, const uint8_t* str2, const atInt32 len);
LZLengthOffset windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr,
atUint8* startLBPtr);
atInt32 subMatch(const atUint8* str1, const uint8_t* str2, const atInt32 len);
LZLengthOffset windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr, atUint8* startLBPtr);
protected: protected:
LZLengthOffset search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd); LZLengthOffset search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd);
atInt32 m_slidingWindow;
atInt32 m_readAheadBuffer;
atInt32 m_minMatch;//Minimum number of bytes that have to matched to go through with compression
atInt32 m_blockSize;
atUint32 m_minOffset;
LZLookupTable m_lookupTable;
atInt32 m_slidingWindow;
atInt32 m_readAheadBuffer;
atInt32 m_minMatch; // Minimum number of bytes that have to matched to go through with compression
atInt32 m_blockSize;
atUint32 m_minOffset;
LZLookupTable m_lookupTable;
}; };

View File

@ -6,32 +6,25 @@
#include <cstdint> #include <cstdint>
#include <athena/Types.hpp> #include <athena/Types.hpp>
struct LZLengthOffset struct LZLengthOffset {
{ atUint32 length; // The number of bytes compressed
atUint32 length;//The number of bytes compressed atUint16 offset; // How far back in sliding window where bytes that match the lookAheadBuffer is located
atUint16 offset;//How far back in sliding window where bytes that match the lookAheadBuffer is located bool compare_equal(const LZLengthOffset& lo_pair) { return length == lo_pair.length && offset == lo_pair.offset; }
bool compare_equal(const LZLengthOffset& lo_pair)
{
return length == lo_pair.length && offset == lo_pair.offset;
}
}; };
class LZLookupTable class LZLookupTable {
{
public: public:
LZLookupTable(); LZLookupTable();
LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow = 4096, atInt32 lookAheadWindow = 18); LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow = 4096, atInt32 lookAheadWindow = 18);
~LZLookupTable(); ~LZLookupTable();
LZLengthOffset search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd); LZLengthOffset search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd);
void setLookAheadWindow(atInt32 lookAheadWindow); void setLookAheadWindow(atInt32 lookAheadWindow);
private: private:
typedef std::multimap<std::vector<uint8_t>, int32_t> LookupTable; typedef std::multimap<std::vector<uint8_t>, int32_t> LookupTable;
LookupTable table; LookupTable table;
atInt32 m_minimumMatch; atInt32 m_minimumMatch;
atInt32 m_slidingWindow; atInt32 m_slidingWindow;
atInt32 m_lookAheadWindow; atInt32 m_lookAheadWindow;
std::vector<uint8_t> m_buffer; std::vector<uint8_t> m_buffer;
}; };

View File

@ -2,11 +2,10 @@
#include "LZBase.hpp" #include "LZBase.hpp"
class LZType10 : public LZBase class LZType10 : public LZBase {
{
public: public:
explicit LZType10(atInt32 minimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3, atInt32 BlockSize = 8); explicit LZType10(atInt32 minimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3,
atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength); atInt32 BlockSize = 8);
atUint32 decompress(const atUint8* src, atUint8** dst, atUint32 srcLen); atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength);
atUint32 decompress(const atUint8* src, atUint8** dst, atUint32 srcLen);
}; };

View File

@ -1,14 +1,11 @@
#pragma once #pragma once
#include "LZBase.hpp" #include "LZBase.hpp"
class LZType11 : public LZBase class LZType11 : public LZBase {
{
public: public:
explicit LZType11(atInt32 MinimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3, atInt32 BlockSize = 8); explicit LZType11(atInt32 MinimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3,
atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength); atInt32 BlockSize = 8);
atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength); atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength);
atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength);
}; };

View File

@ -4,19 +4,16 @@
#include <cstdlib> #include <cstdlib>
#include <memory> #include <memory>
namespace athena namespace athena {
{
class IAES class IAES {
{
public: public:
virtual ~IAES() {} virtual ~IAES() {}
virtual void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)=0; 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 decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len) = 0;
virtual void setKey(const uint8_t* key)=0; virtual void setKey(const uint8_t* key) = 0;
}; };
std::unique_ptr<IAES> NewAES(); std::unique_ptr<IAES> NewAES();
} } // namespace athena

View File

@ -2,92 +2,56 @@
#include "Types.hpp" #include "Types.hpp"
namespace athena namespace athena {
{
enum BowType : char enum BowType : char { BowNone, BowArrows, BowSilverArrows };
{
BowNone, enum BoomerangType : char { BoomerangNone, BoomerangBlue, BoomerangRed };
BowArrows,
BowSilverArrows enum MagicType : char { MagicNone, MagicMushroom, MagicPowder };
enum ArmorType : char { GreenJerkin, BlueMail, RedMail };
enum BottleType : char {
BottleNone,
BottleMushroom, // No Use
BottleEmpty,
BottleRedPotion,
BottleBluePotion,
BottleFairy,
BottleBee,
BottleGoodBee
}; };
enum BoomerangType : char enum ALTTPStartLocation { LinksHouse = 0x00, Sanctuary = 0x01, Any = 0x05 };
{
BoomerangNone, enum ALTTPProgressIndicator { LinkInBed, InCastleWithSword, CompletedFirstDungeon, BeatenAghanim };
BoomerangBlue,
BoomerangRed enum ALTTPMapIcon {
Nothing = 0x00, //?
CrossInKakariko = 0x01, //?
CrossAtFirstDungeon = 0x02, //
Pendant = 0x03,
MasterSword = 0x04,
AganhimCastle = 0x05,
Crystal1 = 0x06,
AllCrystals = 0x07,
AganhimGanonTower = 0x08
}; };
enum MagicType : char enum ALTTPTagAlong {
{ Noone,
MagicNone, Zelda,
MagicMushroom, Unknown1,
MagicPowder Oldman,
ZeldaMessage,
Blind,
DwarfFrog,
DwarfLW,
Kiki,
Unknown2,
TheifsChest,
AfterBoss
}; };
enum ArmorType : char } // namespace athena
{
GreenJerkin,
BlueMail,
RedMail
};
enum BottleType : char
{
BottleNone,
BottleMushroom, // No Use
BottleEmpty,
BottleRedPotion,
BottleBluePotion,
BottleFairy,
BottleBee,
BottleGoodBee
};
enum ALTTPStartLocation
{
LinksHouse = 0x00,
Sanctuary = 0x01,
Any = 0x05
};
enum ALTTPProgressIndicator
{
LinkInBed,
InCastleWithSword,
CompletedFirstDungeon,
BeatenAghanim
};
enum ALTTPMapIcon
{
Nothing = 0x00, //?
CrossInKakariko = 0x01, //?
CrossAtFirstDungeon = 0x02, //
Pendant = 0x03,
MasterSword = 0x04,
AganhimCastle = 0x05,
Crystal1 = 0x06,
AllCrystals = 0x07,
AganhimGanonTower = 0x08
};
enum ALTTPTagAlong
{
Noone,
Zelda,
Unknown1,
Oldman,
ZeldaMessage,
Blind,
DwarfFrog,
DwarfLW,
Kiki,
Unknown2,
TheifsChest,
AfterBoss
};
} // zelda

View File

@ -3,8 +3,7 @@
#include "athena/Global.hpp" #include "athena/Global.hpp"
#include <vector> #include <vector>
namespace athena namespace athena {
{
class ALTTPQuest; class ALTTPQuest;
@ -14,61 +13,58 @@ class ALTTPQuest;
* Contains all relevant data for an A Link to the Past * Contains all relevant data for an A Link to the Past
* SRM file. * SRM file.
*/ */
class ALTTPFile class ALTTPFile {
{
public: public:
/*! \brief Quest Iterator /*! \brief Quest Iterator
* *
* An Iterator typedef for iterating through the Quest lists * An Iterator typedef for iterating through the Quest lists
*/ */
typedef std::vector<ALTTPQuest*>::iterator QuestIter; typedef std::vector<ALTTPQuest*>::iterator QuestIter;
/*! \brief Default constructor /*! \brief Default constructor
* *
* *
*/ */
ALTTPFile(); ALTTPFile();
/*! \brief Constructor /*! \brief Constructor
* *
* \param questList The primary quest list * \param questList The primary quest list
* \param backupList The backup quest list * \param backupList The backup quest list
*/ */
ALTTPFile(std::vector<ALTTPQuest*> questList, std::vector<ALTTPQuest*> backupList); ALTTPFile(std::vector<ALTTPQuest*> questList, std::vector<ALTTPQuest*> backupList);
/*! \brief Sets a quest at the given index
*
* \param id Index to the given quest
* \param val The new quest to assign to the given index
* \throw InvalidOperationException on index out of range
*/
void setQuest(atUint32 id, ALTTPQuest* val);
/*! \brief Returns the primary quest list
*
* \return The primary quest list
*/
std::vector<ALTTPQuest*> questList() const;
/*! \brief Sets a quest at the given index /*! \brief Returns a quest at the given index
* *
* \param id Index to the given quest * Returns a quest at the given index
* \param val The new quest to assign to the given index *
* \throw InvalidOperationException on index out of range * \return ALTTPQuest*
*/ * \throw InvalidOperationException on index out of range
void setQuest(atUint32 id, ALTTPQuest* val); */
/*! \brief Returns the primary quest list ALTTPQuest* quest(atUint32 id) const;
*
* \return The primary quest list
*/
std::vector<ALTTPQuest*> questList() const;
/*! \brief Returns a quest at the given index /*! \brief Returns the number of primary quests
* *
* Returns a quest at the given index * \return The number of quests
* */
* \return ALTTPQuest* atUint32 questCount() const;
* \throw InvalidOperationException on index out of range
*/
ALTTPQuest* quest(atUint32 id) const;
/*! \brief Returns the number of primary quests
*
* \return The number of quests
*/
atUint32 questCount() const;
private: private:
std::vector<ALTTPQuest*> m_quests;
std::vector<ALTTPQuest*> m_quests; std::vector<ALTTPQuest*> m_backup;
std::vector<ALTTPQuest*> m_backup;
}; };
} // zelda } // namespace athena

View File

@ -5,12 +5,10 @@
#include "athena/MemoryReader.hpp" #include "athena/MemoryReader.hpp"
#include "athena/ALTTPQuest.hpp" #include "athena/ALTTPQuest.hpp"
namespace athena namespace athena {
{
class ALTTPFile; class ALTTPFile;
namespace io namespace io {
{
/*! \class ALTTPFileReader /*! \class ALTTPFileReader
* \brief A Link to the Past save data reader class * \brief A Link to the Past save data reader class
* *
@ -18,32 +16,32 @@ namespace io
* all work is done using a memory buffer, and not read directly from the disk. * all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class ALTTPFileReader : protected MemoryCopyReader class ALTTPFileReader : protected MemoryCopyReader {
{
public: public:
/*! \brief This constructor takes an existing buffer to read from. /*! \brief This constructor takes an existing buffer to read from.
* *
* \param data The existing buffer * \param data The existing buffer
* \param length The length of the existing buffer * \param length The length of the existing buffer
*/ */
ALTTPFileReader(atUint8*, atUint64); ALTTPFileReader(atUint8*, atUint64);
/*! \brief This constructor creates an instance from a file on disk. /*! \brief This constructor creates an instance from a file on disk.
* *
* \param filename The file to create the stream from * \param filename The file to create the stream from
*/ */
ALTTPFileReader(const std::string&); ALTTPFileReader(const std::string&);
/*! \brief Reads the SRAM data from the buffer
*
* \return ALTTPFile* SRAM data
*/
ALTTPFile* readFile();
/*! \brief Reads the SRAM data from the buffer
*
* \return ALTTPFile* SRAM data
*/
ALTTPFile* readFile();
private: private:
ALTTPRoomFlags* readRoomFlags(); ALTTPRoomFlags* readRoomFlags();
ALTTPOverworldEvent* readOverworldEvent(); ALTTPOverworldEvent* readOverworldEvent();
ALTTPDungeonItemFlags readDungeonFlags(); ALTTPDungeonItemFlags readDungeonFlags();
}; };
} // io } // namespace io
} // zelda } // namespace athena

View File

@ -4,12 +4,10 @@
#include "athena/MemoryWriter.hpp" #include "athena/MemoryWriter.hpp"
#include "athena/ALTTPQuest.hpp" #include "athena/ALTTPQuest.hpp"
namespace athena namespace athena {
{
class ALTTPFile; class ALTTPFile;
namespace io namespace io {
{
/*! \class ALTTPFileWriter /*! \class ALTTPFileWriter
* \brief A Link to the Past save data writer class * \brief A Link to the Past save data writer class
* *
@ -17,35 +15,33 @@ namespace io
* all work is done using a memory buffer, and not written directly to the disk. * all work is done using a memory buffer, and not written directly to the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class ALTTPFileWriter : protected MemoryCopyWriter class ALTTPFileWriter : protected MemoryCopyWriter {
{
public: public:
/*! \brief This constructor takes an existing buffer to write to. /*! \brief This constructor takes an existing buffer to write to.
* *
* \param data The existing buffer * \param data The existing buffer
* \param length The length of the existing buffer * \param length The length of the existing buffer
*/ */
ALTTPFileWriter(atUint8*, atUint64); ALTTPFileWriter(atUint8*, atUint64);
/*! \brief This constructor creates an instance from a file on disk. /*! \brief This constructor creates an instance from a file on disk.
* *
* \param filename The file to create the stream from * \param filename The file to create the stream from
*/ */
ALTTPFileWriter(const std::string&); ALTTPFileWriter(const std::string&);
/*! \brief Writes the given SRAM data to a file on disk /*! \brief Writes the given SRAM data to a file on disk
* *
* \param file SRAM data to right * \param file SRAM data to right
*/ */
void writeFile(ALTTPFile* file); void writeFile(ALTTPFile* file);
private: private:
void writeRoomFlags(ALTTPRoomFlags*); void writeRoomFlags(ALTTPRoomFlags*);
void writeOverworldEvent(ALTTPOverworldEvent*); void writeOverworldEvent(ALTTPOverworldEvent*);
void writeDungeonItems(ALTTPDungeonItemFlags); void writeDungeonItems(ALTTPDungeonItemFlags);
atUint16 calculateChecksum(atUint32 game); atUint16 calculateChecksum(atUint32 game);
}; };
} // io } // namespace io
} // zelda } // namespace athena

File diff suppressed because it is too large Load Diff

View File

@ -3,196 +3,176 @@
#include <string> #include <string>
#include "athena/Types.hpp" #include "athena/Types.hpp"
namespace athena namespace athena {
{
struct ALTTPRoomFlags struct ALTTPRoomFlags {
{ bool Chest1 : 1;
bool Chest1: 1; bool Chest2 : 1;
bool Chest2: 1; bool Chest3 : 1;
bool Chest3: 1; bool Chest4 : 1;
bool Chest4: 1; bool Quadrant1 : 1;
bool Quadrant1: 1; bool Quadrant2 : 1;
bool Quadrant2: 1; bool Quadrant3 : 1;
bool Quadrant3: 1; bool Quadrant4 : 1;
bool Quadrant4: 1; bool Door1 : 1;
bool Door1: 1; bool Door2 : 1;
bool Door2: 1; bool Door3 : 1;
bool Door3: 1; bool Door4 : 1;
bool Door4: 1; bool BossBattleWon : 1;
bool BossBattleWon: 1; bool Key : 1;
bool Key: 1; bool KeyOrChest : 1;
bool KeyOrChest: 1; bool ChestOrTile : 1;
bool ChestOrTile: 1;
}; };
struct ALTTPOverworldEvent struct ALTTPOverworldEvent {
{ bool Unused1 : 1;
bool Unused1: 1; bool HeartPiece : 1;
bool HeartPiece: 1; bool Overlay : 1;
bool Overlay: 1; bool Unused2 : 1;
bool Unused2: 1; bool Unused3 : 1;
bool Unused3: 1; bool Unused4 : 1;
bool Unused4: 1; bool Set : 1;
bool Set: 1; bool Unused5 : 1;
bool Unused5: 1;
}; };
struct ALTTPInventory struct ALTTPInventory {
{ char Bow;
char Bow; char Boomerang;
char Boomerang; bool Hookshot;
bool Hookshot; char Bombs; // Bomb count
char Bombs; // Bomb count char Magic;
char Magic; bool FireRod;
bool FireRod; bool IceRod;
bool IceRod; bool Bombos;
bool Bombos; bool Ether;
bool Ether; bool Quake;
bool Quake; bool Torch;
bool Torch; bool Hammer;
bool Hammer; char Flute;
char Flute; bool BugNet;
bool BugNet; bool Book;
bool Book; bool Bottles;
bool Bottles; bool Somaria;
bool Somaria; bool Byrna;
bool Byrna; bool MagicCape;
bool MagicCape; char MagicMirror;
char MagicMirror; char Gloves;
char Gloves; char Boots;
char Boots; bool Flippers;
bool Flippers; bool MoonPearl;
bool MoonPearl; char Unused; //?
char Unused; //? char Sword;
char Sword; char Shield;
char Shield; char Armor;
char Armor; char BottleTypes[4];
char BottleTypes[4];
}; };
/*! \struct ALTTPLightDarkWorldIndicator /*! \struct ALTTPLightDarkWorldIndicator
*/ */
struct ALTTPLightDarkWorldIndicator struct ALTTPLightDarkWorldIndicator {
{ bool Unused1 : 1;
bool Unused1: 1; bool Unused2 : 1;
bool Unused2: 1; bool Unused3 : 1;
bool Unused3: 1; bool Unused4 : 1;
bool Unused4: 1; bool Unused5 : 1;
bool Unused5: 1; bool Unused6 : 1;
bool Unused6: 1; bool IsDarkWorld : 1;
bool IsDarkWorld: 1; bool Unused7 : 1;
bool Unused7: 1;
}; };
struct ALTTPDungeonItemFlags {
struct ALTTPDungeonItemFlags union {
{ struct {
union bool Unused1 : 1;
{ bool Unused2 : 1;
struct bool GanonsTower : 1;
{ bool TurtleRock : 1;
bool Unused1: 1; bool GargoylesDomain : 1;
bool Unused2: 1; bool TowerOfHera : 1;
bool GanonsTower: 1; bool IcePalace : 1;
bool TurtleRock: 1; bool SkullWoods : 1;
bool GargoylesDomain: 1;
bool TowerOfHera: 1;
bool IcePalace: 1;
bool SkullWoods: 1;
};
atUint8 flags1;
}; };
atUint8 flags1;
};
union union {
{ struct {
struct bool MiseryMire : 1;
{ bool DarkPalace : 1;
bool MiseryMire: 1; bool SwampPalace : 1;
bool DarkPalace: 1; bool HyruleCastle2 : 1; // unused in orignal game
bool SwampPalace: 1; bool DesertPalace : 1;
bool HyruleCastle2: 1; // unused in orignal game bool EasternPalace : 1;
bool DesertPalace: 1; bool HyruleCastle : 1; // unused exist in original game
bool EasternPalace: 1; bool SewerPassage : 1; // unused exist in original game
bool HyruleCastle: 1; // unused exist in original game
bool SewerPassage: 1; // unused exist in original game
};
atUint8 flags2;
}; };
atUint8 flags2;
};
}; };
struct ALTTPPendants struct ALTTPPendants {
{ bool Courage : 1;
bool Courage: 1; bool Wisdom : 1;
bool Wisdom: 1; bool Power : 1;
bool Power: 1; bool Unused1 : 1;
bool Unused1: 1; bool Unused2 : 1;
bool Unused2: 1; bool Unused3 : 1;
bool Unused3: 1; bool Unused4 : 1;
bool Unused4: 1; bool Unused5 : 1;
bool Unused5: 1;
}; };
struct ALTTPAbilities struct ALTTPAbilities {
{ bool Nothing : 1; //?
bool Nothing: 1; //? bool Swim : 1;
bool Swim: 1; bool Dash : 1;
bool Dash: 1; bool Pull : 1;
bool Pull: 1; bool Unknown1 : 1; //---
bool Unknown1: 1; //--- bool Talk : 1;
bool Talk: 1; bool Read : 1;
bool Read: 1; bool Unknown2 : 1; //---
bool Unknown2: 1; //---
}; };
struct ALTTPCrystals struct ALTTPCrystals {
{ bool MiseryMire : 1;
bool MiseryMire: 1; bool DarkPalace : 1;
bool DarkPalace: 1; bool IcePalace : 1;
bool IcePalace: 1; bool TurtleRock : 1;
bool TurtleRock: 1; bool SwampPalace : 1;
bool SwampPalace: 1; bool GargoyleDomain : 1;
bool GargoyleDomain: 1; bool SkullWoods : 1;
bool SkullWoods: 1;
}; };
struct ALTTPMagicUsage struct ALTTPMagicUsage {
{ bool Normal : 1;
bool Normal: 1; bool Half : 1;
bool Half: 1; bool Quarter : 1;
bool Quarter: 1; bool Unused1 : 1;
bool Unused1: 1; bool Unused2 : 1;
bool Unused2: 1; bool Unused3 : 1;
bool Unused3: 1; bool Unused4 : 1;
bool Unused4: 1; bool Unused5 : 1;
bool Unused5: 1;
}; };
struct ALTTPProgressFlags1 {
struct ALTTPProgressFlags1 bool UncleSecretPassage : 1;
{ bool DyingPriest : 1; //?
bool UncleSecretPassage: 1; bool ZeldaSanctuary : 1; //?
bool DyingPriest: 1; //? bool Unused1 : 1;
bool ZeldaSanctuary: 1; //? bool UncleLeftHouse : 1;
bool Unused1: 1; bool BookOfMudora : 1; //? Math says it's a guess need to investigate
bool UncleLeftHouse: 1; bool DwarfPartner : 1; //?
bool BookOfMudora: 1; //? Math says it's a guess need to investigate bool Unused2 : 1;
bool DwarfPartner: 1; //?
bool Unused2: 1;
}; };
struct ALTTPProgressFlags2 {
struct ALTTPProgressFlags2 bool BottleFromBum : 1;
{ bool BottleFromSalesMen : 1;
bool BottleFromBum: 1; bool Unused1 : 1; //?
bool BottleFromSalesMen: 1; bool FluteBoy : 1;
bool Unused1: 1; //? bool ThiefsChest : 1;
bool FluteBoy: 1; bool SavedSmithPartner : 1;
bool ThiefsChest: 1; bool Unused2 : 1; //?
bool SavedSmithPartner: 1; bool SmithsHaveSword : 1;
bool Unused2: 1; //?
bool SmithsHaveSword: 1;
}; };
} } // namespace athena

View File

@ -2,10 +2,10 @@
#include "athena/Global.hpp" #include "athena/Global.hpp"
namespace athena::checksums namespace athena::checksums {
{ atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed = 0xFFFFFFFFFFFFFFFF,
atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed = 0xFFFFFFFFFFFFFFFF, atUint64 final = 0xFFFFFFFFFFFFFFFF); atUint64 final = 0xFFFFFFFFFFFFFFFF);
atUint32 crc32(const atUint8* data, atUint64 length, atUint32 seed = 0xFFFFFFFF, atUint32 final = 0xFFFFFFFF); atUint32 crc32(const atUint8* data, atUint64 length, atUint32 seed = 0xFFFFFFFF, atUint32 final = 0xFFFFFFFF);
atUint16 crc16CCITT(const atUint8* data, atUint64 length, atUint16 seed = 0xFFFF, atUint16 final = 0); atUint16 crc16CCITT(const atUint8* data, atUint64 length, atUint16 seed = 0xFFFF, atUint16 final = 0);
atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed = 0, atUint16 final = 0); atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed = 0, atUint16 final = 0);
} } // namespace athena::checksums

View File

@ -2,196 +2,161 @@
#include <cstdint> #include <cstdint>
namespace athena::checksums::literals namespace athena::checksums::literals {
{
constexpr uint32_t crc32_table[] = constexpr uint32_t crc32_table[] = {
{ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832,
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, template <uint32_t CRC, char... Chars>
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, struct Crc32Impl {};
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
template <uint32_t CRC, char Head, char... Tail>
struct Crc32Impl<CRC, Head, Tail...> {
static constexpr uint32_t value =
Crc32Impl<crc32_table[static_cast<unsigned char>(CRC) ^ static_cast<unsigned char>(Head)] ^ (CRC >> 8),
Tail...>::value;
}; };
template<uint32_t CRC, char ...Chars> struct Crc32Impl { template <uint32_t CRC>
struct Crc32Impl<CRC> {
static constexpr uint32_t value = CRC ^ 0xFFFFFFFF;
}; };
template<uint32_t CRC, char Head, char ...Tail> struct Crc32Impl<CRC, Head, Tail...> { template <char... Chars>
static constexpr uint32_t value = Crc32Impl< using Crc32 = Crc32Impl<0xFFFFFFFF, Chars...>;
crc32_table[static_cast<unsigned char>(CRC) ^ static_cast<unsigned char>(Head)]
^ (CRC >> 8), Tail...>::value;
};
template<uint32_t CRC> struct Crc32Impl<CRC> { constexpr uint32_t crc32_rec(uint32_t crc, const char* s) {
static constexpr uint32_t value = CRC ^ 0xFFFFFFFF; return *s == 0 ? crc ^ 0xFFFFFFFF
}; : crc32_rec(crc32_table[static_cast<unsigned char>(crc) ^ static_cast<unsigned char>(*s)] ^ (crc >> 8),
s + 1);
template<char ...Chars> using Crc32 = Crc32Impl<0xFFFFFFFF, Chars...>;
constexpr uint32_t crc32_rec(uint32_t crc, const char *s) {
return *s == 0 ? crc ^ 0xFFFFFFFF :
crc32_rec(crc32_table[static_cast<unsigned char>(crc) ^
static_cast<unsigned char>(*s)]
^ (crc >> 8), s + 1);
} }
constexpr uint32_t operator "" _crc32(const char *s, size_t len) { constexpr uint32_t operator"" _crc32(const char* s, size_t len) { return crc32_rec(0xFFFFFFFF, s); }
return crc32_rec(0xFFFFFFFF, s);
static_assert("Hello"_crc32 == Crc32<'H', 'e', 'l', 'l', 'o'>::value, "CRC32 values don't match");
static_assert("0"_crc32 == Crc32<'0'>::value, "CRC32 values don't match");
constexpr uint32_t rcrc32_rec(uint32_t crc, const char* s) {
return *s == 0 ? crc
: crc32_rec(crc32_table[static_cast<unsigned char>(crc) ^ static_cast<unsigned char>(*s)] ^ (crc >> 8),
s + 1);
} }
static_assert("Hello"_crc32 == Crc32<'H', 'e', 'l', 'l', 'o'>::value, constexpr uint32_t operator"" _rcrc32(const char* s, size_t len) { return rcrc32_rec(0xFFFFFFFF, s); }
"CRC32 values don't match");
static_assert("0"_crc32 == Crc32<'0'>::value,
"CRC32 values don't match");
static_assert("Hello"_rcrc32 == Crc32<'H', 'e', 'l', 'l', 'o'>::value, "CRC32 values don't match");
static_assert("0"_rcrc32 == Crc32<'0'>::value, "CRC32 values don't match");
constexpr uint32_t rcrc32_rec(uint32_t crc, const char *s) { constexpr uint64_t crc64_table[] = {
return *s == 0 ? crc : 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, 0x493366450E42ECDF,
crc32_rec(crc32_table[static_cast<unsigned char>(crc) ^ 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A, 0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D,
static_cast<unsigned char>(*s)] 0x17870F5D4F51B498, 0x5577EEB6E6BB820B, 0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847,
^ (crc >> 8), s + 1); 0x1C4488F3E8F96ED4, 0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A,
} 0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285, 0xF45BB4758C645C51,
0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4, 0xBD68D2308226B08E, 0xFF9833DB2BCC861D,
0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B, 0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8,
0x0B6BD3C3DBFD506B, 0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4,
0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5, 0x172F5B3033043EBF,
0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A, 0xAA478900B1228E31, 0xE8B768EB18C8B8A2,
0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584, 0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8,
0x2465CD79455E395B, 0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A,
0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5, 0xDA050215EA6C212F,
0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A, 0x93366450E42ECDF0, 0xD1C685BB4DC4FB63,
0x16D7A787B7FAA0D6, 0x5427466C1E109645, 0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7,
0x8F72ECA30CD7A324, 0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB,
0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75, 0xF50B1CAF74CF481F,
0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA, 0x2E5EB66066087D7E, 0x6CAE578BCFE24BED,
0xABBF75B735DC1058, 0xE94F945C9C3626CB, 0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87,
0xA07CF2199274CA14, 0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144,
0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B, 0x84193F60D72AF34F,
0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA, 0xCD2A5925D9681F90, 0x8FDAB8CE70822903,
0x48CB9AF28ABC72B6, 0x0A3B7B1923564425, 0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238,
0xB753A929A170F4AB, 0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874,
0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15, 0xAB1721DA49899A7F,
0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA, 0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E,
0x731B26172EE619EB, 0x31EBC7FC870C2F78, 0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534,
0x78D8A1B9894EC3A7, 0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6,
0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19, 0x90C79D3FEDD3F122,
0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97, 0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E,
0x5C1538ADB04570DB, 0x1EE5D94619AF4648, 0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA,
0xC5B073890B687329, 0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6,
0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6, 0x73B3727A52B393CC,
0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879, 0xA8E6D8B54074A6AD, 0xEA16395EE99E903E,
0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18, 0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754,
0x26C49CCCB40811C7, 0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149,
0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96, 0xCEDBA04AD0952342,
0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7, 0x87E8C60FDED7CF9D, 0xC51827E4773DF90E,
0x020905D88D03A2BB, 0x40F9E43324E99428, 0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4,
0xEBEEC5E96D600E57, 0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288,
0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9, 0xF7AA4D1A85996083,
0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36, 0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E,
0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8, 0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4,
0xC4E0DB53F3C36767, 0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206,
0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9, 0xE085162AB69D5E3C,
0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589, 0xA9B6706FB8DFB2E3, 0xEB46918411358470,
0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956, 0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4,
0xB5F2F89C5026DC37, 0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8,
0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066, 0xCF8B0890283E370C,
0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9, 0x14DEA25F3AF9026D, 0x562E43B4931334FE,
0x913F6188692D6F4B, 0xD3CF8063C0C759D8, 0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394,
0x9AFCE626CE85B507};
constexpr uint32_t operator "" _rcrc32(const char *s, size_t len) { template <uint64_t CRC, char... Chars>
return rcrc32_rec(0xFFFFFFFF, s); struct Crc64Impl {};
}
static_assert("Hello"_rcrc32 == Crc32<'H', 'e', 'l', 'l', 'o'>::value, template <uint64_t CRC, char Head, char... Tail>
"CRC32 values don't match"); struct Crc64Impl<CRC, Head, Tail...> {
static_assert("0"_rcrc32 == Crc32<'0'>::value, static constexpr uint64_t value =
"CRC32 values don't match"); Crc64Impl<crc64_table[static_cast<unsigned char>(CRC >> 56) ^ static_cast<unsigned char>(Head)] ^ (CRC << 8),
Tail...>::value;
constexpr uint64_t crc64_table[] =
{
0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5,
0x493366450E42ECDF, 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A,
0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B,
0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, 0x1C4488F3E8F96ED4,
0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A,
0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285,
0xF45BB4758C645C51, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4,
0xBD68D2308226B08E, 0xFF9833DB2BCC861D, 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B,
0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, 0x0B6BD3C3DBFD506B,
0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4,
0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5,
0x172F5B3033043EBF, 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A,
0xAA478900B1228E31, 0xE8B768EB18C8B8A2, 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584,
0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8, 0x2465CD79455E395B,
0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A,
0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5,
0xDA050215EA6C212F, 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A,
0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, 0x16D7A787B7FAA0D6, 0x5427466C1E109645,
0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, 0x8F72ECA30CD7A324,
0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB,
0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75,
0xF50B1CAF74CF481F, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA,
0x2E5EB66066087D7E, 0x6CAE578BCFE24BED, 0xABBF75B735DC1058, 0xE94F945C9C3626CB,
0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, 0xA07CF2199274CA14,
0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144,
0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B,
0x84193F60D72AF34F, 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA,
0xCD2A5925D9681F90, 0x8FDAB8CE70822903, 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425,
0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238, 0xB753A929A170F4AB,
0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874,
0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15,
0xAB1721DA49899A7F, 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA,
0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, 0x731B26172EE619EB, 0x31EBC7FC870C2F78,
0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, 0x78D8A1B9894EC3A7,
0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6,
0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19,
0x90C79D3FEDD3F122, 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97,
0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E, 0x5C1538ADB04570DB, 0x1EE5D94619AF4648,
0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, 0xC5B073890B687329,
0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6,
0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6,
0x73B3727A52B393CC, 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879,
0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18,
0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754, 0x26C49CCCB40811C7,
0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149,
0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96,
0xCEDBA04AD0952342, 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7,
0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, 0x020905D88D03A2BB, 0x40F9E43324E99428,
0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, 0xEBEEC5E96D600E57,
0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288,
0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9,
0xF7AA4D1A85996083, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36,
0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E, 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8,
0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, 0xC4E0DB53F3C36767,
0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206,
0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9,
0xE085162AB69D5E3C, 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589,
0xA9B6706FB8DFB2E3, 0xEB46918411358470, 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956,
0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4, 0xB5F2F89C5026DC37,
0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8,
0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066,
0xCF8B0890283E370C, 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9,
0x14DEA25F3AF9026D, 0x562E43B4931334FE, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8,
0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, 0x9AFCE626CE85B507
}; };
template<uint64_t CRC, char ...Chars> struct Crc64Impl { template <uint64_t CRC>
struct Crc64Impl<CRC> {
static constexpr uint64_t value = CRC ^ 0xFFFFFFFFFFFFFFFF;
}; };
template<uint64_t CRC, char Head, char ...Tail> struct Crc64Impl<CRC, Head, Tail...> { template <char... Chars>
static constexpr uint64_t value = Crc64Impl< using Crc64 = Crc64Impl<0xFFFFFFFFFFFFFFFF, Chars...>;
crc64_table[static_cast<unsigned char>(CRC >> 56) ^ static_cast<unsigned char>(Head)]
^ (CRC << 8), Tail...>::value;
};
template<uint64_t CRC> struct Crc64Impl<CRC> { constexpr uint64_t crc64_rec(uint64_t crc, const char* s) {
static constexpr uint64_t value = CRC ^ 0xFFFFFFFFFFFFFFFF; return *s == 0 ? crc ^ 0xFFFFFFFFFFFFFFFF
}; : crc64_rec(crc64_table[static_cast<unsigned char>(crc >> 56) ^ static_cast<unsigned char>(*s)] ^
(crc << 8),
s + 1);
template<char ...Chars> using Crc64 = Crc64Impl<0xFFFFFFFFFFFFFFFF, Chars...>;
constexpr uint64_t crc64_rec(uint64_t crc, const char *s) {
return *s == 0 ? crc ^ 0xFFFFFFFFFFFFFFFF :
crc64_rec(crc64_table[static_cast<unsigned char>(crc >> 56) ^
static_cast<unsigned char>(*s)]
^ (crc << 8), s + 1);
} }
constexpr uint64_t operator "" _crc64(const char *s, size_t len) { constexpr uint64_t operator"" _crc64(const char* s, size_t len) { return crc64_rec(0xFFFFFFFFFFFFFFFF, s); }
return crc64_rec(0xFFFFFFFFFFFFFFFF, s);
}
static_assert("Hello"_crc64 == Crc64<'H', 'e', 'l', 'l', 'o'>::value,
"CRC64 values don't match");
static_assert("0"_crc64 == Crc64<'0'>::value,
"CRC64 values don't match");
}
static_assert("Hello"_crc64 == Crc64<'H', 'e', 'l', 'l', 'o'>::value, "CRC64 values don't match");
static_assert("0"_crc64 == Crc64<'0'>::value, "CRC64 values don't match");
} // namespace athena::checksums::literals

View File

@ -2,8 +2,7 @@
#include "athena/Global.hpp" #include "athena/Global.hpp"
namespace athena::io::Compression namespace athena::io::Compression {
{
// Zlib compression // Zlib compression
atInt32 decompressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen); atInt32 decompressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen);
atInt32 compressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen); atInt32 compressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen);
@ -17,4 +16,4 @@ atUint32 yaz0Encode(const atUint8* src, atUint32 srcSize, atUint8* data);
atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst); atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst);
atUint32 compressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst, bool extended = false); atUint32 compressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst, bool extended = false);
} } // namespace athena::io::Compression

View File

@ -13,8 +13,7 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
namespace athena::io namespace athena::io {
{
/** /**
* @brief Base DNA class used against 'atdna' * @brief Base DNA class used against 'atdna'
@ -26,81 +25,80 @@ namespace athena::io
* a streamed medium * a streamed medium
*/ */
template <Endian DNAE> template <Endian DNAE>
struct DNA struct DNA {
{ /**
/** * @brief Designated byte-order used for serializing fields
* @brief Designated byte-order used for serializing fields */
*/ static constexpr Endian DNAEndian = DNAE;
static constexpr Endian DNAEndian = DNAE;
/** /**
* @brief Template type signaling atdna to capture the value where it's used * @brief Template type signaling atdna to capture the value where it's used
* @tparam T The type of the value. Can be any numeric type or atVec* type * @tparam T The type of the value. Can be any numeric type or atVec* type
* @tparam VE Endianness of the value * @tparam VE Endianness of the value
*/ */
template <typename T, Endian VE = DNAE> template <typename T, Endian VE = DNAE>
using Value = T; using Value = T;
/** /**
* @brief Template type wrapping std::vector and signaling atdna to manipulate it where it's used * @brief Template type wrapping std::vector and signaling atdna to manipulate it where it's used
* @tparam T The type of contained elements. Can be any numeric type, atVec* type, or another DNA subclass * @tparam T The type of contained elements. Can be any numeric type, atVec* type, or another DNA subclass
* @tparam cntVar C++ expression wrapped in DNA_COUNT macro to determine number of elements for vector * @tparam cntVar C++ expression wrapped in DNA_COUNT macro to determine number of elements for vector
* @tparam VE Endianness of the contained values * @tparam VE Endianness of the contained values
*/ */
template <typename T, size_t cntVar, Endian VE = DNAE> template <typename T, size_t cntVar, Endian VE = DNAE>
using Vector = std::vector<T>; using Vector = std::vector<T>;
/** /**
* @brief Template type wrapping std::unique_ptr<atUint8[]> and signaling atdna to read a * @brief Template type wrapping std::unique_ptr<atUint8[]> and signaling atdna to read a
* raw byte-buffer where it's used * raw byte-buffer where it's used
* @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of bytes for buffer * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of bytes for buffer
*/ */
template <size_t sizeVar> template <size_t sizeVar>
using Buffer = std::unique_ptr<atUint8[]>; using Buffer = std::unique_ptr<atUint8[]>;
/** /**
* @brief Template type wrapping std::string and signaling atdna to read string data where it's used * @brief Template type wrapping std::string and signaling atdna to read string data where it's used
* @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for string * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for string
* -1 literal indicates null-terminated string * -1 literal indicates null-terminated string
*/ */
template <atInt32 sizeVar = -1> template <atInt32 sizeVar = -1>
using String = std::string; using String = std::string;
/** /**
* @brief Template type wrapping std::wstring and signaling atdna to read wstring data where it's used * @brief Template type wrapping std::wstring and signaling atdna to read wstring data where it's used
* @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for wstring * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for wstring
* -1 literal indicates null-terminated wstring * -1 literal indicates null-terminated wstring
*/ */
template <atInt32 sizeVar = -1, Endian VE = DNAE> template <atInt32 sizeVar = -1, Endian VE = DNAE>
using WString = std::wstring; using WString = std::wstring;
/** /**
* @brief Meta Template signaling atdna to insert a stream seek where it's used * @brief Meta Template signaling atdna to insert a stream seek where it's used
* @tparam offset C++ expression wrapped in DNA_COUNT macro to determine number of bytes to seek * @tparam offset C++ expression wrapped in DNA_COUNT macro to determine number of bytes to seek
* @tparam direction SeekOrigin to seek relative to * @tparam direction SeekOrigin to seek relative to
*/ */
template <off_t offset, SeekOrigin direction> template <off_t offset, SeekOrigin direction>
struct Seek {}; struct Seek {};
/** /**
* @brief Meta Template signaling atdna to insert an aligning stream seek where it's used * @brief Meta Template signaling atdna to insert an aligning stream seek where it's used
* @tparam align Number of bytes to align to * @tparam align Number of bytes to align to
*/ */
template <size_t align> template <size_t align>
struct Align {}; struct Align {};
/** /**
* @brief Meta Template preventing atdna from emitting read/write implementations * @brief Meta Template preventing atdna from emitting read/write implementations
*/ */
struct Delete {}; struct Delete {};
/* Bring fundamental operations into DNA subclasses for easier per-op overrides */ /* Bring fundamental operations into DNA subclasses for easier per-op overrides */
using Read = athena::io::Read<PropType::None>; using Read = athena::io::Read<PropType::None>;
using Write = athena::io::Write<PropType::None>; using Write = athena::io::Write<PropType::None>;
using BinarySize = athena::io::BinarySize<PropType::None>; using BinarySize = athena::io::BinarySize<PropType::None>;
using PropCount = athena::io::PropCount<PropType::None>; using PropCount = athena::io::PropCount<PropType::None>;
using ReadYaml = athena::io::ReadYaml<PropType::None>; using ReadYaml = athena::io::ReadYaml<PropType::None>;
using WriteYaml = athena::io::WriteYaml<PropType::None>; using WriteYaml = athena::io::WriteYaml<PropType::None>;
}; };
/** /**
@ -120,24 +118,22 @@ struct DNA
* { (Do stuff with `r`) } * { (Do stuff with `r`) }
*/ */
template <Endian DNAE> template <Endian DNAE>
struct DNAV : DNA<DNAE> struct DNAV : DNA<DNAE> {
{ virtual ~DNAV() = default;
virtual ~DNAV() = default; virtual void read(athena::io::IStreamReader& r) = 0;
virtual void read(athena::io::IStreamReader& r) = 0; virtual void write(athena::io::IStreamWriter& w) const = 0;
virtual void write(athena::io::IStreamWriter& w) const = 0; virtual void binarySize(size_t& s) const = 0;
virtual void binarySize(size_t& s) const = 0; virtual const char* DNATypeV() const = 0;
virtual const char* DNATypeV() const = 0;
}; };
template <Endian DNAE> template <Endian DNAE>
struct DNAVYaml : DNAV<DNAE> struct DNAVYaml : DNAV<DNAE> {
{ virtual ~DNAVYaml() = default;
virtual ~DNAVYaml() = default; virtual void read(athena::io::IStreamReader& r) = 0;
virtual void read(athena::io::IStreamReader& r) = 0; virtual void write(athena::io::IStreamWriter& w) const = 0;
virtual void write(athena::io::IStreamWriter& w) const = 0; virtual void binarySize(size_t& s) const = 0;
virtual void binarySize(size_t& s) const = 0; virtual void read(athena::io::YAMLDocReader& r) = 0;
virtual void read(athena::io::YAMLDocReader& r) = 0; virtual void write(athena::io::YAMLDocWriter& w) const = 0;
virtual void write(athena::io::YAMLDocWriter& w) const = 0;
}; };
/** Macro to supply count variable to atdna and mute it for other compilers */ /** Macro to supply count variable to atdna and mute it for other compilers */
@ -147,6 +143,4 @@ struct DNAVYaml : DNAV<DNAE>
#define AT_DNA_COUNT(cnt) 0 #define AT_DNA_COUNT(cnt) 0
#endif #endif
} } // namespace athena::io

File diff suppressed because it is too large Load Diff

View File

@ -6,132 +6,116 @@
#include "FileReader.hpp" #include "FileReader.hpp"
#include "FileWriter.hpp" #include "FileWriter.hpp"
namespace athena::io namespace athena::io {
{
template <class T> template <class T>
static inline const char* __GetDNAName(const T& dna, static inline const char* __GetDNAName(const T& dna, typename std::enable_if_t<athena::io::__IsDNAVRecord_v<T>>* = 0) {
typename std::enable_if_t<athena::io::__IsDNAVRecord_v<T>>* = 0) return dna.DNATypeV();
{
return dna.DNATypeV();
} }
template <class T> template <class T>
static inline const char* __GetDNAName(const T& dna, static inline const char* __GetDNAName(const T& dna, typename std::enable_if_t<!athena::io::__IsDNAVRecord_v<T>>* = 0) {
typename std::enable_if_t<!athena::io::__IsDNAVRecord_v<T>>* = 0) return dna.DNAType();
{
return dna.DNAType();
} }
template <class T> template <class T>
static inline std::string ToYAMLString(const T& dna) static inline std::string ToYAMLString(const T& dna) {
{ YAMLDocWriter docWriter(__GetDNAName(dna));
YAMLDocWriter docWriter(__GetDNAName(dna));
std::string res; std::string res;
yaml_emitter_set_output(docWriter.getEmitter(), (yaml_write_handler_t*)YAMLStdStringWriter, &res); yaml_emitter_set_output(docWriter.getEmitter(), (yaml_write_handler_t*)YAMLStdStringWriter, &res);
yaml_emitter_set_unicode(docWriter.getEmitter(), true); yaml_emitter_set_unicode(docWriter.getEmitter(), true);
yaml_emitter_set_width(docWriter.getEmitter(), -1); yaml_emitter_set_width(docWriter.getEmitter(), -1);
dna.write(docWriter); dna.write(docWriter);
if (!docWriter.finish(nullptr)) if (!docWriter.finish(nullptr))
return std::string(); return std::string();
return res; return res;
} }
template <class T> template <class T>
static inline bool FromYAMLString(T& dna, std::string_view str) static inline bool FromYAMLString(T& dna, std::string_view str) {
{ YAMLStdStringViewReaderState reader(str);
YAMLStdStringViewReaderState reader(str); YAMLDocReader docReader;
YAMLDocReader docReader; yaml_parser_set_input(docReader.getParser(), (yaml_read_handler_t*)YAMLStdStringReader, &reader);
yaml_parser_set_input(docReader.getParser(), (yaml_read_handler_t*)YAMLStdStringReader, &reader); if (!docReader.parse(nullptr))
if (!docReader.parse(nullptr)) return false;
return false; dna.read(docReader);
dna.read(docReader); return true;
return true;
} }
template<class DNASubtype> template <class DNASubtype>
static inline bool ValidateFromYAMLString(std::string_view str) static inline bool ValidateFromYAMLString(std::string_view str) {
{ YAMLStdStringViewReaderState reader(str);
YAMLStdStringViewReaderState reader(str); YAMLDocReader docReader;
YAMLDocReader docReader; yaml_parser_set_input(docReader.getParser(), (yaml_read_handler_t*)YAMLStdStringReader, &reader);
yaml_parser_set_input(docReader.getParser(), (yaml_read_handler_t*)YAMLStdStringReader, &reader); bool retval = docReader.ValidateClassType(DNASubtype::DNAType());
bool retval = docReader.ValidateClassType(DNASubtype::DNAType()); return retval;
return retval;
} }
template <class T> template <class T>
static inline bool ToYAMLStream(const T& dna, athena::io::IStreamWriter& fout) static inline bool ToYAMLStream(const T& dna, athena::io::IStreamWriter& fout) {
{ YAMLDocWriter docWriter(__GetDNAName(dna));
YAMLDocWriter docWriter(__GetDNAName(dna));
yaml_emitter_set_unicode(docWriter.getEmitter(), true); yaml_emitter_set_unicode(docWriter.getEmitter(), true);
yaml_emitter_set_width(docWriter.getEmitter(), -1); yaml_emitter_set_width(docWriter.getEmitter(), -1);
dna.write(docWriter); dna.write(docWriter);
return docWriter.finish(&fout); return docWriter.finish(&fout);
} }
template <class T> template <class T>
static inline bool ToYAMLStream(const T& dna, athena::io::IStreamWriter& fout, static inline bool ToYAMLStream(const T& dna, athena::io::IStreamWriter& fout,
void(T::*fn)(YAMLDocWriter& out)const) void (T::*fn)(YAMLDocWriter& out) const) {
{ YAMLDocWriter docWriter(__GetDNAName(dna));
YAMLDocWriter docWriter(__GetDNAName(dna));
yaml_emitter_set_unicode(docWriter.getEmitter(), true); yaml_emitter_set_unicode(docWriter.getEmitter(), true);
yaml_emitter_set_width(docWriter.getEmitter(), -1); yaml_emitter_set_width(docWriter.getEmitter(), -1);
(dna.*fn)(docWriter); (dna.*fn)(docWriter);
return docWriter.finish(&fout); return docWriter.finish(&fout);
} }
template <class T> template <class T>
static inline bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin) static inline bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin) {
{ YAMLDocReader docReader;
YAMLDocReader docReader; if (!docReader.parse(&fin))
if (!docReader.parse(&fin)) return false;
return false; dna.read(docReader);
dna.read(docReader); return true;
return true;
} }
template <class T> template <class T>
static inline bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin, static inline bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin, void (T::*fn)(YAMLDocReader& in)) {
void(T::*fn)(YAMLDocReader& in)) YAMLDocReader docReader;
{ if (!docReader.parse(&fin))
YAMLDocReader docReader; return false;
if (!docReader.parse(&fin)) (dna.*fn)(docReader);
return false; return true;
(dna.*fn)(docReader);
return true;
} }
template <class T, typename NameT> template <class T, typename NameT>
static inline bool MergeToYAMLFile(const T& dna, const NameT& filename) static inline bool MergeToYAMLFile(const T& dna, const NameT& filename) {
{ athena::io::FileReader r(filename);
athena::io::FileReader r(filename); YAMLDocWriter docWriter(__GetDNAName(dna), r.isOpen() ? &r : nullptr);
YAMLDocWriter docWriter(__GetDNAName(dna), r.isOpen() ? &r : nullptr); r.close();
r.close();
dna.write(docWriter); dna.write(docWriter);
athena::io::FileWriter w(filename); athena::io::FileWriter w(filename);
if (!w.isOpen()) if (!w.isOpen())
return false; return false;
return docWriter.finish(&w); return docWriter.finish(&w);
} }
template <class DNASubtype> template <class DNASubtype>
static inline bool ValidateFromYAMLStream(athena::io::IStreamReader& fin) static inline bool ValidateFromYAMLStream(athena::io::IStreamReader& fin) {
{ YAMLDocReader reader;
YAMLDocReader reader; atUint64 pos = fin.position();
atUint64 pos = fin.position(); yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)YAMLAthenaReader, &fin);
yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)YAMLAthenaReader, &fin); bool retval = reader.ValidateClassType(DNASubtype::DNAType());
bool retval = reader.ValidateClassType(DNASubtype::DNAType()); fin.seek(pos, athena::Begin);
fin.seek(pos, athena::Begin); return retval;
return retval;
}
} }
} // namespace athena::io

View File

@ -8,30 +8,26 @@
typedef int mode_t; typedef int mode_t;
#endif #endif
namespace athena namespace athena {
{ class Dir {
class Dir
{
public: public:
explicit Dir(std::string_view path); explicit Dir(std::string_view path);
std::string absolutePath() const; std::string absolutePath() const;
static inline std::string absolutePath(std::string_view path) static inline std::string absolutePath(std::string_view path) { return Dir(path).absolutePath(); }
{ return Dir(path).absolutePath(); }
bool isDir() const; bool isDir() const;
static bool isDir(std::string_view dir) static bool isDir(std::string_view dir) { return Dir(dir).isDir(); }
{ return Dir(dir).isDir(); }
std::vector<FileInfo> files() const; std::vector<FileInfo> files() const;
bool cd(std::string_view path);
bool rm(std::string_view path);
bool touch();
static bool mkdir(std::string_view dir, mode_t mode = 0755);
static bool mkpath(std::string_view path, mode_t mode = 0755);
bool cd(std::string_view path);
bool rm(std::string_view path);
bool touch();
static bool mkdir(std::string_view dir, mode_t mode = 0755);
static bool mkpath(std::string_view path, mode_t mode = 0755);
private: private:
std::string m_path; std::string m_path;
}; };
} } // namespace athena

View File

@ -4,54 +4,41 @@
#include "athena/Global.hpp" #include "athena/Global.hpp"
namespace athena namespace athena {
{ class FileInfo {
class FileInfo
{
public: public:
explicit FileInfo(std::string_view path = {}); explicit FileInfo(std::string_view path = {});
std::string absolutePath() const; std::string absolutePath() const;
static inline std::string absolutePath(std::string_view lnk) static inline std::string absolutePath(std::string_view lnk) { return FileInfo(lnk).absolutePath(); }
{ return FileInfo(lnk).absolutePath(); }
std::string absoluteFilePath() const; std::string absoluteFilePath() const;
static inline std::string absoluteFilePath(std::string_view path) static inline std::string absoluteFilePath(std::string_view path) { return FileInfo(path).absoluteFilePath(); }
{ return FileInfo(path).absoluteFilePath(); }
std::string filename() const; std::string filename() const;
static inline std::string filename(std::string_view path) static inline std::string filename(std::string_view path) { return FileInfo(path).filename(); }
{ return FileInfo(path).filename(); }
std::string path() const { return m_path; } std::string path() const { return m_path; }
static inline std::string path(std::string_view path) static inline std::string path(std::string_view path) { return FileInfo(path).path(); }
{ return FileInfo(path).path(); }
std::string extension() const; std::string extension() const;
static inline std::string extension(std::string_view path) static inline std::string extension(std::string_view path) { return FileInfo(path).extension(); }
{ return FileInfo(path).extension(); }
atUint64 size() const; atUint64 size() const;
static inline atUint64 size(std::string_view path) static inline atUint64 size(std::string_view path) { return FileInfo(path).size(); }
{ return FileInfo(path).size(); }
bool exists() const; bool exists() const;
static inline bool exists(std::string_view path) static inline bool exists(std::string_view path) { return FileInfo(path).exists(); }
{ return FileInfo(path).exists(); }
bool isLink() const; bool isLink() const;
static inline bool isLink(std::string_view lnk) static inline bool isLink(std::string_view lnk) { return FileInfo(lnk).isLink(); }
{ return FileInfo(lnk).isLink(); } bool isFile() const;
bool isFile() const; static inline bool isFile(std::string_view path) { return FileInfo(path).isFile(); }
static inline bool isFile(std::string_view path)
{ return FileInfo(path).isFile(); }
bool touch() const; bool touch() const;
static inline bool touch(std::string_view path) static inline bool touch(std::string_view path) { return FileInfo(path).touch(); }
{ return FileInfo(path).touch(); }
private: private:
std::string m_path; std::string m_path;
}; };
} } // namespace athena

View File

@ -13,71 +13,66 @@
#include <memory> #include <memory>
#include "athena/IStreamReader.hpp" #include "athena/IStreamReader.hpp"
namespace athena::io namespace athena::io {
{ class FileReader : public IStreamReader {
class FileReader : public IStreamReader
{
public: public:
FileReader(std::string_view filename, atInt32 cacheSize = (32 * 1024), bool globalErr=true); FileReader(std::string_view filename, atInt32 cacheSize = (32 * 1024), bool globalErr = true);
FileReader(std::wstring_view filename, atInt32 cacheSize = (32 * 1024), bool globalErr=true); FileReader(std::wstring_view filename, atInt32 cacheSize = (32 * 1024), bool globalErr = true);
virtual ~FileReader(); virtual ~FileReader();
inline std::string filename() const inline std::string filename() const {
{
#if _WIN32 #if _WIN32
return utility::wideToUtf8(m_filename); return utility::wideToUtf8(m_filename);
#else #else
return m_filename; return m_filename;
#endif #endif
} }
inline std::wstring wfilename() const inline std::wstring wfilename() const {
{
#if _WIN32 #if _WIN32
return m_filename; return m_filename;
#else #else
return utility::utf8ToWide(m_filename); return utility::utf8ToWide(m_filename);
#endif #endif
} }
void open(); void open();
void close(); void close();
inline bool isOpen() const inline bool isOpen() const { return m_fileHandle != 0; }
{return m_fileHandle != 0;} bool save();
bool save(); void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); atUint64 position() const;
atUint64 position() const; atUint64 length() const;
atUint64 length() const; atUint64 readUBytesToBuf(void* buf, atUint64 len);
atUint64 readUBytesToBuf(void* buf, atUint64 len);
void setCacheSize(const atInt32 blockSize); void setCacheSize(const atInt32 blockSize);
#if _WIN32 #if _WIN32
using HandleType = HANDLE; using HandleType = HANDLE;
#else #else
using HandleType = FILE*; using HandleType = FILE*;
#endif #endif
HandleType _fileHandle() {return m_fileHandle;} HandleType _fileHandle() { return m_fileHandle; }
protected: protected:
#if _WIN32 #if _WIN32
std::wstring m_filename; std::wstring m_filename;
#else #else
std::string m_filename; std::string m_filename;
#endif #endif
HandleType m_fileHandle; HandleType m_fileHandle;
std::unique_ptr<atUint8[]> m_cacheData; std::unique_ptr<atUint8[]> m_cacheData;
atInt32 m_blockSize; atInt32 m_blockSize;
atInt32 m_curBlock; atInt32 m_curBlock;
atUint64 m_offset; atUint64 m_offset;
bool m_globalErr; bool m_globalErr;
}; };
} // Athena } // namespace athena::io
#ifndef FILEREADER_BASE #ifndef FILEREADER_BASE
#define FILEREADER_BASE() \ #define FILEREADER_BASE() \
private: \ private: \
typedef athena::io::FileReader base typedef athena::io::FileReader base
#endif // FILEREADER_BASE #endif // FILEREADER_BASE

View File

@ -10,112 +10,107 @@
#endif #endif
#include "athena/IStreamWriter.hpp" #include "athena/IStreamWriter.hpp"
namespace athena::io namespace athena::io {
{ class FileWriter : public IStreamWriter {
class FileWriter : public IStreamWriter
{
public: public:
FileWriter(std::string_view filename, bool overwrite = true, bool globalErr=true); FileWriter(std::string_view filename, bool overwrite = true, bool globalErr = true);
FileWriter(std::wstring_view filename, bool overwrite = true, bool globalErr=true); FileWriter(std::wstring_view filename, bool overwrite = true, bool globalErr = true);
virtual ~FileWriter(); virtual ~FileWriter();
inline std::string filename() const inline std::string filename() const {
{
#if _WIN32 #if _WIN32
return utility::wideToUtf8(m_filename); return utility::wideToUtf8(m_filename);
#else #else
return m_filename; return m_filename;
#endif #endif
} }
inline std::wstring wfilename() const inline std::wstring wfilename() const {
{
#if _WIN32 #if _WIN32
return m_filename; return m_filename;
#else #else
return utility::utf8ToWide(m_filename); return utility::utf8ToWide(m_filename);
#endif #endif
} }
void open(bool overwrite = true); void open(bool overwrite = true);
void close(); void close();
inline bool isOpen() const inline bool isOpen() const { return m_fileHandle != 0; }
{return m_fileHandle != 0;} void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); atUint64 position() const;
atUint64 position() const; atUint64 length() const;
atUint64 length() const; void writeUBytes(const atUint8* data, atUint64 len);
void writeUBytes(const atUint8* data, atUint64 len);
#if _WIN32 #if _WIN32
using HandleType = HANDLE; using HandleType = HANDLE;
#else #else
using HandleType = FILE*; using HandleType = FILE*;
#endif #endif
HandleType _fileHandle() {return m_fileHandle;} HandleType _fileHandle() { return m_fileHandle; }
private: private:
#if _WIN32 #if _WIN32
std::wstring m_filename; std::wstring m_filename;
#else #else
std::string m_filename; std::string m_filename;
#endif #endif
HandleType m_fileHandle; HandleType m_fileHandle;
bool m_globalErr; bool m_globalErr;
}; };
class TransactionalFileWriter : public IStreamWriter class TransactionalFileWriter : public IStreamWriter {
{
#if _WIN32 #if _WIN32
std::wstring m_filename; std::wstring m_filename;
#else #else
std::string m_filename; std::string m_filename;
#endif #endif
bool m_overwrite, m_globalErr; bool m_overwrite, m_globalErr;
std::vector<uint8_t> m_deferredBuffer; std::vector<uint8_t> m_deferredBuffer;
atUint64 m_position = 0; atUint64 m_position = 0;
public: public:
TransactionalFileWriter(std::string_view filename, bool overwrite = true, bool globalErr=true) TransactionalFileWriter(std::string_view filename, bool overwrite = true, bool globalErr = true)
: m_overwrite(overwrite), m_globalErr(globalErr) : m_overwrite(overwrite), m_globalErr(globalErr) {
{
#if _WIN32 #if _WIN32
m_filename = utility::utf8ToWide(filename); m_filename = utility::utf8ToWide(filename);
#else #else
m_filename = filename; m_filename = filename;
#endif #endif
} }
TransactionalFileWriter(std::wstring_view filename, bool overwrite = true, bool globalErr=true) TransactionalFileWriter(std::wstring_view filename, bool overwrite = true, bool globalErr = true)
: m_overwrite(overwrite), m_globalErr(globalErr) : m_overwrite(overwrite), m_globalErr(globalErr) {
{
#if _WIN32 #if _WIN32
m_filename = filename; m_filename = filename;
#else #else
m_filename = utility::wideToUtf8(filename); m_filename = utility::wideToUtf8(filename);
#endif #endif
}
void flush() {
if (m_deferredBuffer.size()) {
FileWriter w(m_filename, m_overwrite, m_globalErr);
w.writeUBytes(m_deferredBuffer.data(), m_deferredBuffer.size());
cancel();
} }
}
void flush() void cancel() {
{ m_deferredBuffer.clear();
if (m_deferredBuffer.size()) m_position = 0;
{ }
FileWriter w(m_filename, m_overwrite, m_globalErr);
w.writeUBytes(m_deferredBuffer.data(), m_deferredBuffer.size());
cancel();
}
}
void cancel() { m_deferredBuffer.clear(); m_position = 0; } inline atUint64 position() const { return m_position; }
inline atUint64 length() const { return m_deferredBuffer.size(); }
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
void writeUBytes(const atUint8* data, atUint64 len);
inline atUint64 position() const { return m_position; } ~TransactionalFileWriter() { flush(); }
inline atUint64 length() const { return m_deferredBuffer.size(); }
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
void writeUBytes(const atUint8* data, atUint64 len);
~TransactionalFileWriter() { flush(); }
}; };
} // Athena } // namespace athena::io
#ifndef FILEWRITER_BASE #ifndef FILEWRITER_BASE
#define FILEWRITER_BASE() \ #define FILEWRITER_BASE() \
private: \ private: \
typedef athena::io::FileWriter base; typedef athena::io::FileWriter base;
#endif // FILEWRITER_BASE #endif // FILEWRITER_BASE

View File

@ -82,80 +82,57 @@ typedef struct stat64 atStat64_t;
#ifndef ENABLE_BITWISE_ENUM #ifndef ENABLE_BITWISE_ENUM
#define ENABLE_BITWISE_ENUM(type) \ #define ENABLE_BITWISE_ENUM(type) \
constexpr type operator|(type a, type b) \ constexpr type operator|(type a, type b) { \
{ \ using T = std::underlying_type_t<type>; \
using T = std::underlying_type_t<type>; \ return type(static_cast<T>(a) | static_cast<T>(b)); \
return type(static_cast<T>(a) | static_cast<T>(b)); \ } \
} \ constexpr type operator&(type a, type b) { \
constexpr type operator&(type a, type b) \ using T = std::underlying_type_t<type>; \
{ \ return type(static_cast<T>(a) & static_cast<T>(b)); \
using T = std::underlying_type_t<type>; \ } \
return type(static_cast<T>(a) & static_cast<T>(b)); \ inline type& operator|=(type& a, const type& b) { \
} \ using T = std::underlying_type_t<type>; \
inline type& operator|=(type& a, const type& b) \ a = type(static_cast<T>(a) | static_cast<T>(b)); \
{ \ return a; \
using T = std::underlying_type_t<type>; \ } \
a = type(static_cast<T>(a) | static_cast<T>(b)); \ inline type& operator&=(type& a, const type& b) { \
return a; \ using T = std::underlying_type_t<type>; \
} \ a = type(static_cast<T>(a) & static_cast<T>(b)); \
inline type& operator&=(type& a, const type& b) \ return a; \
{ \ } \
using T = std::underlying_type_t<type>; \ inline type operator~(const type& key) { \
a = type(static_cast<T>(a) & static_cast<T>(b)); \ using T = std::underlying_type_t<type>; \
return a; \ return type(~static_cast<T>(key)); \
} \ }
inline type operator~(const type& key) \
{ \
using T = std::underlying_type_t<type>; \
return type(~static_cast<T>(key)); \
}
#endif #endif
namespace athena namespace athena {
{ namespace error {
namespace error enum class Level { Message, Warning, Error, Fatal };
{
enum class Level
{
Message,
Warning,
Error,
Fatal
};
} }
enum SeekOrigin enum SeekOrigin { Begin, Current, End };
{
Begin,
Current,
End
};
enum Endian enum Endian { Little, Big };
{
Little,
Big
};
namespace io namespace io {
{
template <Endian DNAE> template <Endian DNAE>
struct DNA; struct DNA;
template <Endian DNAE> template <Endian DNAE>
struct DNAV; struct DNAV;
template <class T> template <class T>
using __IsDNARecord = typename std::disjunction<std::is_base_of<DNA<Endian::Big>, T>, using __IsDNARecord =
std::is_base_of<DNA<Endian::Little>, T>>; typename std::disjunction<std::is_base_of<DNA<Endian::Big>, T>, std::is_base_of<DNA<Endian::Little>, T>>;
template <class T> template <class T>
inline constexpr bool __IsDNARecord_v = __IsDNARecord<T>::value; inline constexpr bool __IsDNARecord_v = __IsDNARecord<T>::value;
template <class T> template <class T>
using __IsDNAVRecord = typename std::disjunction<std::is_base_of<DNAV<Endian::Big>, T>, using __IsDNAVRecord =
std::is_base_of<DNAV<Endian::Little>, T>>; typename std::disjunction<std::is_base_of<DNAV<Endian::Big>, T>, std::is_base_of<DNAV<Endian::Little>, T>>;
template <class T> template <class T>
inline constexpr bool __IsDNAVRecord_v = __IsDNAVRecord<T>::value; inline constexpr bool __IsDNAVRecord_v = __IsDNAVRecord<T>::value;
} } // namespace io
} // Athena } // namespace athena
typedef void (*atEXCEPTION_HANDLER)(athena::error::Level level, const char* file, const char* function, int line, typedef void (*atEXCEPTION_HANDLER)(athena::error::Level level, const char* file, const char* function, int line,
const char* fmt, ...); const char* fmt, ...);
@ -173,91 +150,80 @@ std::ostream& operator<<(std::ostream& os, const athena::Endian& endian);
#ifdef _MSC_VER #ifdef _MSC_VER
#ifndef NDEBUG #ifndef NDEBUG
#define atDebug(fmt, ...) \ #define atDebug(fmt, ...) \
do \ do { \
{ \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \
if (__handler) \ __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \
__handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ } while (0)
} while (0)
#else #else
#define atDebug(fmt, ...) #define atDebug(fmt, ...)
#endif #endif
#define atMessage(fmt, ...) \ #define atMessage(fmt, ...) \
do \ do { \
{ \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \
if (__handler) \ __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \
__handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ } while (0)
} while (0)
#define atWarning(fmt, ...) \ #define atWarning(fmt, ...) \
do \ do { \
{ \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \
if (__handler) \ __handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \
__handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ } while (0)
} while (0)
#define atError(fmt, ...) \ #define atError(fmt, ...) \
do \ do { \
{ \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \
if (__handler) \ __handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \
__handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ } while (0)
} while (0)
#define atFatal(fmt, ...) \ #define atFatal(fmt, ...) \
do \ do { \
{ \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \
if (__handler) \ __handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \
__handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ } while (0)
} while (0)
#elif defined(__GNUC__) #elif defined(__GNUC__)
#ifndef NDEBUG #ifndef NDEBUG
#define atDebug(fmt...) \ #define atDebug(fmt...) \
do \ do { \
{ \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \
if (__handler) \ __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \
__handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ } while (0)
} while (0)
#else // _MSC_VER #else // _MSC_VER
#define atDebug(fmt, ...) #define atDebug(fmt, ...)
#endif // NDEBUG #endif // NDEBUG
#define atMessage(fmt...) \ #define atMessage(fmt...) \
do \ do { \
{ \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \
if (__handler) \ __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \
__handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ } while (0)
} while (0)
#define atWarning(fmt...) \ #define atWarning(fmt...) \
do \ do { \
{ \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \
if (__handler) \ __handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \
__handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ } while (0)
} while (0)
#define atError(fmt...) \ #define atError(fmt...) \
do \ do { \
{ \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \
if (__handler) \ __handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \
__handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ } while (0)
} while (0)
#define atFatal(fmt...) \ #define atFatal(fmt...) \
do \ do { \
{ \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \
if (__handler) \ __handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \
__handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ } while (0)
} while (0)
#endif // defined(__GNUC__) #endif // defined(__GNUC__)

View File

@ -2,31 +2,30 @@
#include "Global.hpp" #include "Global.hpp"
namespace athena::io namespace athena::io {
{
std::ostream& operator<<(std::ostream& os, Endian& endian); std::ostream& operator<<(std::ostream& os, Endian& endian);
class IStream class IStream {
{
public: public:
virtual ~IStream() = default; virtual ~IStream() = default;
void setEndian(Endian endian) { m_endian = endian; }
Endian endian() const { return m_endian; }
bool isBigEndian() const { return (m_endian == Endian::Big); }
bool isLittleEndian() const { return (m_endian == Endian::Little); }
virtual void seek(atInt64, SeekOrigin) = 0;
virtual bool atEnd() const = 0;
virtual atUint64 position() const = 0;
virtual atUint64 length() const = 0;
bool hasError() const { return m_hasError; }
void setEndian(Endian endian) { m_endian = endian; }
Endian endian() const { return m_endian; }
bool isBigEndian() const { return (m_endian == Endian::Big); }
bool isLittleEndian() const { return (m_endian == Endian::Little); }
virtual void seek(atInt64, SeekOrigin) = 0;
virtual bool atEnd() const = 0;
virtual atUint64 position() const = 0;
virtual atUint64 length() const = 0;
bool hasError() const { return m_hasError; }
protected: protected:
void setError() { m_hasError = true; } void setError() { m_hasError = true; }
bool m_hasError = false; bool m_hasError = false;
#if __BYTE_ORDER == __BIG_ENDIAN #if __BYTE_ORDER == __BIG_ENDIAN
Endian m_endian = Big; Endian m_endian = Big;
#else #else
Endian m_endian = Little; Endian m_endian = Little;
#endif #endif
}; };
} } // namespace athena::io

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,7 @@
#include "athena/Global.hpp" #include "athena/Global.hpp"
namespace athena namespace athena {
{
class MCSlot; class MCSlot;
/*! \class MCFile /*! \class MCFile
@ -12,23 +11,18 @@ class MCSlot;
* Contains all relevant data for a The Minish Cap save, * Contains all relevant data for a The Minish Cap save,
* file. * file.
*/ */
class MCFile class MCFile {
{
public: public:
static const char VERSION_EU_JP[33]; static const char VERSION_EU_JP[33];
static const char VERSION_US[33]; static const char VERSION_US[33];
enum SlotType enum SlotType { New = 0x54494E49, Valid = 0x4D435A33, Deleted = 0x466C6544 };
{
New = 0x54494E49,
Valid = 0x4D435A33,
Deleted = 0x466C6544
};
MCFile(); MCFile();
static atUint8* unscramble(atUint8* data, atUint64 length);
static atUint8* unscramble(atUint8* data, atUint64 length);
private: private:
MCSlot* m_slots[3]; MCSlot* m_slots[3];
}; };
} // zelda } // namespace athena

View File

@ -2,13 +2,11 @@
#include "athena/MemoryReader.hpp" #include "athena/MemoryReader.hpp"
namespace athena namespace athena {
{
class MCFile; class MCFile;
namespace io namespace io {
{
/*! \class MCFileReader /*! \class MCFileReader
* \brief The Minish Cap Save save data reader class * \brief The Minish Cap Save save data reader class
@ -17,32 +15,30 @@ namespace io
* all work is done using a memory buffer, and not read directly from the disk. * all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class MCFileReader : public MemoryCopyReader class MCFileReader : public MemoryCopyReader {
{
public: public:
/*! /*!
* \brief This constructor takes an existing buffer to read from. * \brief This constructor takes an existing buffer to read from.
* *
* \param data The existing buffer * \param data The existing buffer
* \param length The length of the existing buffer * \param length The length of the existing buffer
*/ */
MCFileReader(atUint8*, atUint64); MCFileReader(atUint8*, atUint64);
/*! /*!
* \brief This constructor creates an instance from a file on disk. * \brief This constructor creates an instance from a file on disk.
* *
* \param filename The file to create the stream from * \param filename The file to create the stream from
*/ */
MCFileReader(const std::string&); MCFileReader(const std::string&);
/*! /*!
* \brief Reads the save data from the buffer * \brief Reads the save data from the buffer
* *
* \return MCFile* SRAM data * \return MCFile* SRAM data
*/ */
MCFile* readFile(); MCFile* readFile();
}; };
} // io } // namespace io
} // zelda } // namespace athena

View File

@ -3,13 +3,11 @@
#include "athena/Types.hpp" #include "athena/Types.hpp"
#include "athena/MemoryWriter.hpp" #include "athena/MemoryWriter.hpp"
namespace athena namespace athena {
{
class MCFile; class MCFile;
namespace io namespace io {
{
/*! \class MCFileWriter /*! \class MCFileWriter
* \brief The Minish Cap Save save data writer class * \brief The Minish Cap Save save data writer class
@ -18,36 +16,35 @@ namespace io
* all work is done using a memory buffer, and not written directly from the disk. * all work is done using a memory buffer, and not written directly from the disk.
* \sa BinaryWriter * \sa BinaryWriter
*/ */
class MCFileWriter : protected MemoryCopyWriter class MCFileWriter : protected MemoryCopyWriter {
{
public: public:
/*! /*!
* \brief This constructor takes an existing buffer to write to. * \brief This constructor takes an existing buffer to write to.
* *
* \param data The existing buffer * \param data The existing buffer
* \param length The length of the existing buffer * \param length The length of the existing buffer
*/ */
MCFileWriter(atUint8*, atUint64); MCFileWriter(atUint8*, atUint64);
/*! /*!
* \brief This constructor creates an instance from a file on disk. * \brief This constructor creates an instance from a file on disk.
* *
* \param filename The file to create the stream from * \param filename The file to create the stream from
*/ */
MCFileWriter(const std::string&); MCFileWriter(const std::string&);
/*! /*!
* \brief Writes the given save data to a file on disk * \brief Writes the given save data to a file on disk
* *
* \param file Save data to write * \param file Save data to write
*/ */
void writeFile(MCFile* file); void writeFile(MCFile* file);
static atUint16 calculateChecksum(atUint8* data, atUint32 length);
static atUint16 calculateChecksum(atUint8* data, atUint32 length);
private: private:
atUint16 calculateSlotChecksum(atUint32 game); atUint16 calculateSlotChecksum(atUint32 game);
}; };
} // io } // namespace io
} // zelda } // namespace athena

View File

@ -3,13 +3,10 @@
#include "athena/Global.hpp" #include "athena/Global.hpp"
#include "athena/ZQuestFile.hpp" #include "athena/ZQuestFile.hpp"
namespace athena namespace athena {
{ class MCSlot : public ZQuestFile {
class MCSlot : public ZQuestFile
{
public: public:
MCSlot(std::unique_ptr<atUint8[]>&& data, atUint32 length); MCSlot(std::unique_ptr<atUint8[]>&& data, atUint32 length);
}; };
} // Athena } // namespace athena

View File

@ -5,8 +5,7 @@
#include <functional> #include <functional>
#include "athena/IStreamReader.hpp" #include "athena/IStreamReader.hpp"
namespace athena::io namespace athena::io {
{
/*! \class MemoryReader /*! \class MemoryReader
* \brief A Stream class for reading data from a memory position * \brief A Stream class for reading data from a memory position
* *
@ -15,106 +14,97 @@ namespace athena::io
* this allows for fast, flexible code as well as the ability to quickly modify data * this allows for fast, flexible code as well as the ability to quickly modify data
* \sa Stream * \sa Stream
*/ */
class MemoryReader : public IStreamReader class MemoryReader : public IStreamReader {
{
protected: protected:
MemoryReader() = default; MemoryReader() = default;
public: public:
virtual ~MemoryReader(); virtual ~MemoryReader();
/*! \brief This constructor references an existing buffer to read from. /*! \brief This constructor references an existing buffer to read from.
* *
* \param data The existing buffer * \param data The existing buffer
* \param length The length of the existing buffer * \param length The length of the existing buffer
* \param takeOwnership Memory will be freed with the reader if set * \param takeOwnership Memory will be freed with the reader if set
*/ */
MemoryReader(const void* data, atUint64 length, bool takeOwnership=false, bool globalErr=true); MemoryReader(const void* data, atUint64 length, bool takeOwnership = false, bool globalErr = true);
/*! \brief Sets the buffers position relative to the specified position.<br /> /*! \brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default. * It seeks relative to the current position by default.
* \param position where in the buffer to seek * \param position where in the buffer to seek
* \param origin The Origin to seek \sa SeekOrigin * \param origin The Origin to seek \sa SeekOrigin
*/ */
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! \brief Returns the current position in the stream. /*! \brief Returns the current position in the stream.
* *
* \return Int64 The current position in the stream. * \return Int64 The current position in the stream.
*/ */
inline atUint64 position() const inline atUint64 position() const { return m_position; }
{return m_position;}
/*! \brief Returns whether or not the stream is at the end. /*! \brief Returns whether or not the stream is at the end.
* *
* \return bool True if at end; False otherwise. * \return bool True if at end; False otherwise.
*/ */
inline atUint64 length() const inline atUint64 length() const { return m_length; }
{return m_length;}
/*! \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 />
* Once you pass the data to setData <b>DO NOT</b> delete the buffer
* as Stream now owns the address, this is done to keep memory usage down.
* \param data The new buffer.
* \param length The length of the new buffer.
* \param takeOwnership Memory will be freed with the reader if set
* \throw IOException
*/
void setData(const atUint8* data, atUint64 length, bool takeOwnership = false);
/*! \brief Sets the buffer to the given one, deleting the current one.<br /> /*! \brief Returns a copy of the current buffer.<br />
* <b>BEWARE:</b> As this deletes the current buffer it WILL cause a loss of data * Changes to the copy do not affect the buffer so it's perfectly safe to
* if that was not the intent.<br /> * directly edit the buffer and use setData to set the new information.<br />
* Once you pass the data to setData <b>DO NOT</b> delete the buffer * However once you pass the data to setData <b>DO NOT</b> delete the buffer
* as Stream now owns the address, this is done to keep memory usage down. * as Stream now owns the address, this is done to keep memory usage down.
* \param data The new buffer. * \return Uint8* The copy of the buffer.
* \param length The length of the new buffer. */
* \param takeOwnership Memory will be freed with the reader if set atUint8* data() const;
* \throw IOException
*/
void setData(const atUint8* data, atUint64 length, bool takeOwnership=false);
/*! \brief Reads a specified number of bytes to user-allocated buffer
/*! \brief Returns a copy of the current buffer.<br /> * \param buf User-allocated buffer pointer
* Changes to the copy do not affect the buffer so it's perfectly safe to * \param len Length to read
* directly edit the buffer and use setData to set the new information.<br /> * \return Number of bytes read
* However once you pass the data to setData <b>DO NOT</b> delete the buffer */
* as Stream now owns the address, this is done to keep memory usage down. atUint64 readUBytesToBuf(void* buf, atUint64 len);
* \return Uint8* The copy of the buffer.
*/
atUint8* data() const;
/*! \brief Reads a specified number of bytes to user-allocated buffer
* \param buf User-allocated buffer pointer
* \param len Length to read
* \return Number of bytes read
*/
atUint64 readUBytesToBuf(void* buf, atUint64 len);
protected: protected:
const void* m_data = nullptr; const void* m_data = nullptr;
atUint64 m_length = 0; atUint64 m_length = 0;
atUint64 m_position = 0; atUint64 m_position = 0;
bool m_owns = false; bool m_owns = false;
bool m_globalErr = true; bool m_globalErr = true;
}; };
class MemoryCopyReader : public MemoryReader class MemoryCopyReader : public MemoryReader {
{
public: public:
/*! \brief This constructor copies an existing buffer to read from. /*! \brief This constructor copies an existing buffer to read from.
* *
* \param data The existing buffer * \param data The existing buffer
* \param length The length of the existing buffer * \param length The length of the existing buffer
*/ */
MemoryCopyReader(const void* data, atUint64 length); MemoryCopyReader(const void* data, atUint64 length);
/*! \brief This constructor creates an instance from a file on disk. /*! \brief This constructor creates an instance from a file on disk.
* *
* \param filename The file to create the stream from * \param filename The file to create the stream from
*/ */
MemoryCopyReader(const std::string& filename) MemoryCopyReader(const std::string& filename) : m_filepath(filename) { loadData(); }
: m_filepath(filename)
{loadData();}
void setData(const atUint8* data, atUint64 length); void setData(const atUint8* data, atUint64 length);
protected: protected:
void loadData(); void loadData();
std::unique_ptr<atUint8[]> m_dataCopy; std::unique_ptr<atUint8[]> m_dataCopy;
std::string m_filepath; //!< Path to the target file std::string m_filepath; //!< Path to the target file
}; };
} // Athena } // namespace athena::io

View File

@ -5,8 +5,7 @@
#include <functional> #include <functional>
#include "athena/IStreamWriter.hpp" #include "athena/IStreamWriter.hpp"
namespace athena::io namespace athena::io {
{
/*! @class MemoryWriter /*! @class MemoryWriter
* @brief A Stream class for writing data to a memory position * @brief A Stream class for writing data to a memory position
@ -16,144 +15,133 @@ namespace athena::io
* this allows for fast, flexible code as well as the ability to quickly modify data * this allows for fast, flexible code as well as the ability to quickly modify data
* @sa Stream * @sa Stream
*/ */
class MemoryWriter : public IStreamWriter class MemoryWriter : public IStreamWriter {
{
public: public:
virtual ~MemoryWriter();
virtual ~MemoryWriter(); /*! @brief This constructor references an existing buffer to write to in-place.
*
* @param data The existing buffer
* @param length The length of the existing buffer
*/
explicit MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership = false);
/*! @brief This constructor references an existing buffer to write to in-place. /*! @brief Sets the buffers position relative to the specified position.<br />
* * It seeks relative to the current position by default.
* @param data The existing buffer * @param position where in the buffer to seek
* @param length The length of the existing buffer * @param origin The Origin to seek @sa SeekOrigin
*/ */
explicit MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership = false); void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! @brief Sets the buffers position relative to the specified position.<br /> /*! @brief Returns the current position in the stream.
* It seeks relative to the current position by default. *
* @param position where in the buffer to seek * @return Int64 The current position in the stream.
* @param origin The Origin to seek @sa SeekOrigin */
*/ inline atUint64 position() const { return m_position; }
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! @brief Returns the length of the stream.
*
* @return Int64 The length of the stream.
*/
inline atUint64 length() const { return m_length; }
/*! @brief Returns the current position in the stream. inline bool isOpen() const { return true; }
*
* @return Int64 The current position in the stream.
*/
inline atUint64 position() const
{return m_position;}
/*! @brief Returns the length of the stream. /** @brief Sets the buffer to the given one, deleting the current one if it owns it.<br />
* * @param data The new buffer.
* @return Int64 The length of the stream. * @param length The length of the new buffer.
*/ * @param takeOwnership Whether the Stream now owns the buffer.
inline atUint64 length() const */
{return m_length;} void setData(atUint8* data, atUint64 length, bool takeOwnership = false);
inline bool isOpen() const {return true;} /*! @brief Returns a copy of the current buffer.<br />
* Changes to the copy do not affect the buffer so it's perfectly safe to
* directly edit the buffer and use setData to set the new information.<br />
* @return Uint8* The copy of the buffer.
*/
atUint8* data() const;
/** @brief Sets the buffer to the given one, deleting the current one if it owns it.<br /> /*! @brief Sets the target file
* @param data The new buffer. *
* @param length The length of the new buffer. * @param filepath The path to write to.
* @param takeOwnership Whether the Stream now owns the buffer. */
*/ inline void setFilepath(const std::string& filepath) { m_filepath = filepath; }
void setData(atUint8* data, atUint64 length, bool takeOwnership = false);
/*! @brief
* Returns the target file
*/
inline std::string filepath() const { return m_filepath; }
/*! @brief Returns a copy of the current buffer.<br /> /*! @brief Saves the file to the specified file.
* Changes to the copy do not affect the buffer so it's perfectly safe to *
* directly edit the buffer and use setData to set the new information.<br /> * @param filename If not empty, the filename to save to
* @return Uint8* The copy of the buffer. */
*/ void save(std::string_view filename = {});
atUint8* data() const;
/*! @brief Sets the target file /*! @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 filepath The path to write to. * If you are needing to fill in an area please use IStreamWriter::fill(atUint64) instead.
*/ *
inline void setFilepath(const std::string& filepath) * @param data The buffer to write
{m_filepath = filepath;} * @param length The amount to write
*/
/*! @brief void writeUBytes(const atUint8* data, atUint64 len);
* Returns the target file
*/
inline std::string filepath() const
{return m_filepath;}
/*! @brief Saves the file to the specified file.
*
* @param filename If not empty, the filename to save to
*/
void save(std::string_view filename = {});
/*! @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.
* If you are needing to fill in an area please use IStreamWriter::fill(atUint64) instead.
*
* @param data The buffer to write
* @param length The amount to write
*/
void writeUBytes(const atUint8* data, atUint64 len);
protected: protected:
MemoryWriter() {} MemoryWriter() {}
atUint8* m_data; atUint8* m_data;
atUint64 m_length; atUint64 m_length;
atUint64 m_position; atUint64 m_position;
bool m_bufferOwned; bool m_bufferOwned;
std::string m_filepath; //!< Path to the target file std::string m_filepath; //!< Path to the target file
}; };
class MemoryCopyWriter : public MemoryWriter class MemoryCopyWriter : public MemoryWriter {
{
public: public:
/*! @brief This constructor copies an existing buffer to write to.
*
* @param data The existing buffer
* @param length The length of the existing buffer
*/
explicit MemoryCopyWriter(atUint8* data = nullptr, atUint64 length = 0x10);
/*! @brief This constructor copies an existing buffer to write to. /*! @brief This constructor creates an instance from a file on disk.
* *
* @param data The existing buffer * @param filename The file to create the stream from
* @param length The length of the existing buffer */
*/ MemoryCopyWriter(std::string_view filename);
explicit MemoryCopyWriter(atUint8* data=nullptr, atUint64 length=0x10);
/*! @brief This constructor creates an instance from a file on disk. /*! @brief Sets the buffers position relative to the specified position.<br />
* * It seeks relative to the current position by default.
* @param filename The file to create the stream from * @param position where in the buffer to seek
*/ * @param origin The Origin to seek @sa SeekOrigin
MemoryCopyWriter(std::string_view filename); */
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! @brief Sets the buffers position relative to the specified position.<br /> /*! @brief Sets the buffer to the given one, deleting the current one.<br />
* It seeks relative to the current position by default. * <b>BEWARE:</b> As this deletes the current buffer it WILL cause a loss of data
* @param position where in the buffer to seek * if that was not the intent.<br />
* @param origin The Origin to seek @sa SeekOrigin * Once you pass the data to setData <b>DO NOT</b> delete the buffer
*/ * as Stream now owns the address, this is done to keep memory usage down.
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); * @param data The new buffer.
* @param length The length of the new buffer.
* @throw IOException
*/
void setData(const atUint8* data, atUint64 length);
/*! @brief Sets the buffer to the given one, deleting the current one.<br /> /*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length
* <b>BEWARE:</b> As this deletes the current buffer it WILL cause a loss of data * however it's undefined behavior to try and write a buffer which is smaller than the given length.
* if that was not the intent.<br /> *
* Once you pass the data to setData <b>DO NOT</b> delete the buffer * @param data The buffer to write
* as Stream now owns the address, this is done to keep memory usage down. * @param length The amount to write
* @param data The new buffer. */
* @param length The length of the new buffer. void writeUBytes(const atUint8* data, atUint64 len);
* @throw IOException
*/
void setData(const atUint8* data, atUint64 length);
/*! @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
*/
void writeUBytes(const atUint8* data, atUint64 len);
protected: protected:
std::unique_ptr<atUint8[]> m_dataCopy; std::unique_ptr<atUint8[]> m_dataCopy;
private: private:
void resize(atUint64 newSize); void resize(atUint64 newSize);
}; };
} } // namespace athena::io

View File

@ -5,54 +5,51 @@
#include "athena/Stream.hpp" #include "athena/Stream.hpp"
#include <physfs.h> #include <physfs.h>
namespace athena::io namespace athena::io {
{ class PHYSFSFileReader : public Stream {
class PHYSFSFileReader : public Stream
{
public: public:
PHYSFSFileReader(const std::string& path); PHYSFSFileReader(const std::string& path);
void setEndian(Endian); void setEndian(Endian);
Endian endian() const; Endian endian() const;
bool isBigEndian() const; bool isBigEndian() const;
bool isLittleEndian() const; bool isLittleEndian() const;
atUint8* data(); atUint8* data();
atUint64 length() const; atUint64 length() const;
atUint64 position() const; atUint64 position() const;
bool isOpen() const; bool isOpen() const;
void seek(atInt64 position, SeekOrigin origin); void seek(atInt64 position, SeekOrigin origin);
atInt8 readByte(); atInt8 readByte();
atUint8 readUByte(); atUint8 readUByte();
atUint8* readUBytes(atUint64 length); atUint8* readUBytes(atUint64 length);
atInt8* readBytes(atUint64 length); atInt8* readBytes(atUint64 length);
atUint16 readUint16(); atUint16 readUint16();
atInt16 readInt16(); atInt16 readInt16();
atUint32 readUint32(); atUint32 readUint32();
atInt32 readInt32(); atInt32 readInt32();
atUint64 readUint64(); atUint64 readUint64();
atInt64 readInt64(); atInt64 readInt64();
double readDouble(); double readDouble();
float readFloat(); float readFloat();
bool readBool(); bool readBool();
bool atEnd() const; bool atEnd() const;
// TODO: Strings // TODO: Strings
private: private:
Endian m_endian; Endian m_endian;
std::string m_path; std::string m_path;
atUint64 m_length; atUint64 m_length;
PHYSFS_File* m_handle; PHYSFS_File* m_handle;
}; };
} } // namespace athena::io
#ifndef PHYSFSFILEREADER_BASE #ifndef PHYSFSFILEREADER_BASE
#define PHYSFSFILEREADER_BASE() \ #define PHYSFSFILEREADER_BASE() typedef athena::io::PHYSFSFileReader base
typedef athena::io::PHYSFSFileReader base
#endif #endif
#endif // PHYSFSSTREAM_HPP #endif // PHYSFSSTREAM_HPP
#endif // ATHENA_ENABLE_PHYSFS #endif // ATHENA_ENABLE_PHYSFS

View File

@ -2,29 +2,18 @@
#include "athena/Global.hpp" #include "athena/Global.hpp"
namespace athena::Sakura namespace athena::Sakura {
{
template <typename T> template <typename T>
class Vector2D class Vector2D {
{
public: public:
T x; T x;
T y; T y;
Vector2D() Vector2D() : x(0), y(0) {}
: x(0),
y(0)
{
}
Vector2D(T x, T y) Vector2D(T x, T y) : x(x), y(y) {}
: x(x),
y(y)
{
}
}; };
typedef Vector2D<int> Vector2Di; typedef Vector2D<int> Vector2Di;
typedef Vector2D<float> Vector2Df; typedef Vector2D<float> Vector2Df;
} // Sakura } // namespace athena::Sakura

View File

@ -5,43 +5,31 @@
// standard lib // standard lib
#include <vector> #include <vector>
namespace athena namespace athena {
{
class SkywardSwordQuest; class SkywardSwordQuest;
enum class Region enum class Region { NTSC, NTSCJ, PAL };
{
NTSC,
NTSCJ,
PAL
};
class SkywardSwordFile class SkywardSwordFile {
{
public: public:
enum MagicNumbers enum MagicNumbers { USMagic = 0x534F5545, JAMagic = 0x534F554A, EUMagic = 0x534F5550 };
{
USMagic = 0x534F5545,
JAMagic = 0x534F554A,
EUMagic = 0x534F5550
};
SkywardSwordFile(); SkywardSwordFile();
SkywardSwordFile(std::vector<SkywardSwordQuest*> quests); SkywardSwordFile(std::vector<SkywardSwordQuest*> quests);
~SkywardSwordFile(); ~SkywardSwordFile();
void addQuest(SkywardSwordQuest* q); void addQuest(SkywardSwordQuest* q);
SkywardSwordQuest* quest(atUint32 id); SkywardSwordQuest* quest(atUint32 id);
std::vector<SkywardSwordQuest*> questList() const; std::vector<SkywardSwordQuest*> questList() const;
void setRegion(Region region); void setRegion(Region region);
Region region() const; Region region() const;
private: private:
Region m_region; Region m_region;
// A vector is a bit overkill // A vector is a bit overkill
std::vector<SkywardSwordQuest*> m_quests; std::vector<SkywardSwordQuest*> m_quests;
atUint32 m_numQuests; atUint32 m_numQuests;
}; };
} } // namespace athena

View File

@ -2,19 +2,15 @@
#include "athena/MemoryReader.hpp" #include "athena/MemoryReader.hpp"
namespace athena namespace athena {
{
class SkywardSwordFile; class SkywardSwordFile;
namespace io namespace io {
{ class SkywardSwordFileReader : public MemoryCopyReader {
class SkywardSwordFileReader : public MemoryCopyReader
{
public: public:
SkywardSwordFileReader(atUint8* data, atUint64 length); SkywardSwordFileReader(atUint8* data, atUint64 length);
SkywardSwordFileReader(const std::string& filename); SkywardSwordFileReader(const std::string& filename);
SkywardSwordFile* read(); SkywardSwordFile* read();
}; };
} // io } // namespace io
} // zelda } // namespace athena

View File

@ -2,20 +2,17 @@
#include "athena/MemoryWriter.hpp" #include "athena/MemoryWriter.hpp"
namespace athena namespace athena {
{
class SkywardSwordFile; class SkywardSwordFile;
namespace io namespace io {
{
class SkywardSwordFileWriter : public MemoryCopyWriter class SkywardSwordFileWriter : public MemoryCopyWriter {
{
public: public:
SkywardSwordFileWriter(atUint8* data, atUint64 len); SkywardSwordFileWriter(atUint8* data, atUint64 len);
SkywardSwordFileWriter(const std::string& filename); SkywardSwordFileWriter(const std::string& filename);
void write(SkywardSwordFile* file); void write(SkywardSwordFile* file);
}; };
} } // namespace io
} } // namespace athena

View File

@ -4,55 +4,48 @@
#include "athena/Global.hpp" #include "athena/Global.hpp"
#include "athena/ZQuestFile.hpp" #include "athena/ZQuestFile.hpp"
namespace athena namespace athena {
{
// TODO: Handle game specific data // TODO: Handle game specific data
class SkywardSwordQuest : public ZQuestFile class SkywardSwordQuest : public ZQuestFile {
{
public: public:
enum AmmoType enum AmmoType { Arrows, Bombs, Seeds };
{
Arrows,
Bombs,
Seeds
};
SkywardSwordQuest(std::unique_ptr<atUint8[]>&& data, atUint32 len); SkywardSwordQuest(std::unique_ptr<atUint8[]>&& data, atUint32 len);
void setPlayerName(const std::string& name); void setPlayerName(const std::string& name);
std::string playerName() const; std::string playerName() const;
void setRupeeCount(atUint16 value); void setRupeeCount(atUint16 value);
atUint16 rupeeCount(); atUint16 rupeeCount();
void setAmmoCount(AmmoType type, atUint32 count); void setAmmoCount(AmmoType type, atUint32 count);
atUint32 ammoCount(AmmoType type); atUint32 ammoCount(AmmoType type);
void setMaxHP(atUint16 val); void setMaxHP(atUint16 val);
atUint16 maxHP(); atUint16 maxHP();
float maxHearts(); float maxHearts();
void setSpawnHP(atUint16 val); void setSpawnHP(atUint16 val);
atUint16 spawnHP(); atUint16 spawnHP();
float spawnHearts(); float spawnHearts();
void setCurrentHP(atUint16 val); void setCurrentHP(atUint16 val);
atUint16 currentHP(); atUint16 currentHP();
float currentHearts(); float currentHearts();
std::string currentLocation(); std::string currentLocation();
std::string currentArea(); std::string currentArea();
std::string currentLocationCopy(); std::string currentLocationCopy();
void setSkipData(std::unique_ptr<atUint8[]>&& data); void setSkipData(std::unique_ptr<atUint8[]>&& data);
atUint8* skipData() const; atUint8* skipData() const;
atUint32 slotChecksum(); atUint32 slotChecksum();
atUint32 skipChecksum(); atUint32 skipChecksum();
void fixChecksums(); void fixChecksums();
void setNew(bool isNew); void setNew(bool isNew);
bool isNew() const; bool isNew() const;
private: private:
std::unique_ptr<atUint8[]> m_skipData; std::unique_ptr<atUint8[]> m_skipData;
}; };
} // Athena } // namespace athena
#endif // SSQUEST_HPP #endif // SSQUEST_HPP

View File

@ -14,89 +14,71 @@ typedef UINT_PTR SOCKET;
struct sockaddr_in; struct sockaddr_in;
namespace athena::net namespace athena::net {
{
/** IP address class derived from SFML */ /** IP address class derived from SFML */
class IPAddress class IPAddress {
{ uint32_t m_address = 0;
uint32_t m_address = 0; bool m_valid = false;
bool m_valid = false;
void resolve(const std::string& address); void resolve(const std::string& address);
public: public:
IPAddress(const std::string& address) IPAddress(const std::string& address) { resolve(address); }
{
resolve(address);
}
uint32_t toInteger() const; uint32_t toInteger() const;
operator bool() const { return m_valid; } operator bool() const { return m_valid; }
}; };
/** Server-oriented TCP socket class derived from SFML */ /** Server-oriented TCP socket class derived from SFML */
class Socket class Socket {
{
#ifndef _WIN32 #ifndef _WIN32
using SocketTp = int; using SocketTp = int;
#else #else
using SocketTp = SOCKET; using SocketTp = SOCKET;
#endif #endif
SocketTp m_socket = -1; SocketTp m_socket = -1;
bool m_isBlocking; bool m_isBlocking;
bool openSocket(); bool openSocket();
void setRemoteSocket(int remSocket); void setRemoteSocket(int remSocket);
public: public:
enum class EResult enum class EResult { OK, Error, Busy };
{
OK,
Error,
Busy
};
#ifdef _WIN32 #ifdef _WIN32
static EResult LastWSAError(); static EResult LastWSAError();
#endif #endif
Socket(bool blocking) Socket(bool blocking) : m_isBlocking(blocking) {}
: m_isBlocking(blocking) {} ~Socket() { close(); }
~Socket() { close(); }
Socket(const Socket& other) = delete; Socket(const Socket& other) = delete;
Socket& operator=(const Socket& other) = delete; Socket& operator=(const Socket& other) = delete;
Socket(Socket&& other) Socket(Socket&& other) : m_socket(other.m_socket), m_isBlocking(other.m_isBlocking) { other.m_socket = -1; }
: m_socket(other.m_socket), m_isBlocking(other.m_isBlocking) Socket& operator=(Socket&& other) {
{ close();
other.m_socket = -1; m_socket = other.m_socket;
} other.m_socket = -1;
Socket& operator=(Socket&& other) m_isBlocking = other.m_isBlocking;
{ return *this;
close(); }
m_socket = other.m_socket;
other.m_socket = -1;
m_isBlocking = other.m_isBlocking;
return *this;
}
void setBlocking(bool blocking); void setBlocking(bool blocking);
bool isOpen() const { return m_socket != -1; } bool isOpen() const { return m_socket != -1; }
bool openAndListen(const IPAddress& address, uint32_t port); bool openAndListen(const IPAddress& address, uint32_t port);
EResult accept(Socket& remoteSocketOut, sockaddr_in& fromAddress); EResult accept(Socket& remoteSocketOut, sockaddr_in& fromAddress);
EResult accept(Socket& remoteSocketOut); EResult accept(Socket& remoteSocketOut);
EResult accept(Socket& remoteSocketOut, std::string& fromHostname); EResult accept(Socket& remoteSocketOut, std::string& fromHostname);
void close(); void close();
EResult send(const void* buf, size_t len, size_t& transferred); EResult send(const void* buf, size_t len, size_t& transferred);
EResult send(const void* buf, size_t len); EResult send(const void* buf, size_t len);
EResult recv(void* buf, size_t len, size_t& transferred); EResult recv(void* buf, size_t len, size_t& transferred);
EResult recv(void* buf, size_t len); EResult recv(void* buf, size_t len);
operator bool() const { return isOpen(); } operator bool() const { return isOpen(); }
SocketTp GetInternalSocket() const { return m_socket; } SocketTp GetInternalSocket() const { return m_socket; }
}; };
} } // namespace athena::net

View File

@ -4,67 +4,65 @@
#include <string> #include <string>
#include "athena/SakuraGlobal.hpp" #include "athena/SakuraGlobal.hpp"
namespace athena::Sakura namespace athena::Sakura {
{
class SpriteFile; class SpriteFile;
class SpriteFrame; class SpriteFrame;
class Sprite class Sprite {
{
public: public:
Sprite(SpriteFile* root); Sprite(SpriteFile* root);
Sprite(SpriteFile* root, const std::string& name); Sprite(SpriteFile* root, const std::string& name);
virtual ~Sprite(); virtual ~Sprite();
virtual void setPosition(const float x, const float y); virtual void setPosition(const float x, const float y);
virtual void setPosition(const Vector2Df& pos); virtual void setPosition(const Vector2Df& pos);
virtual Vector2Df position() const; virtual Vector2Df position() const;
void setName(const std::string& name); void setName(const std::string& name);
std::string name() const; std::string name() const;
void addStateId(int id); void addStateId(int id);
/*! /*!
* \brief Returns the texture id of a given state * \brief Returns the texture id of a given state
* \param index The index of the id. * \param index The index of the id.
* \return return the state id if it exists, -1 otherwise * \return return the state id if it exists, -1 otherwise
*/ */
int stateId(int index) const; int stateId(int index) const;
void setStateIds(std::vector<int> ids); void setStateIds(std::vector<int> ids);
std::vector<int> stateIds() const; std::vector<int> stateIds() const;
atUint32 stateCount() const; atUint32 stateCount() const;
void setCurrentState(atUint32 id); void setCurrentState(atUint32 id);
atUint32 currentState() const; atUint32 currentState() const;
bool addFrame(SpriteFrame* Frame); bool addFrame(SpriteFrame* Frame);
bool removeFrame(SpriteFrame* Frame); bool removeFrame(SpriteFrame* Frame);
SpriteFrame* Frame(atUint32 id); SpriteFrame* Frame(atUint32 id);
void setFrame(atUint32 id); void setFrame(atUint32 id);
void setFrames(std::vector<SpriteFrame*> frames); void setFrames(std::vector<SpriteFrame*> frames);
atUint32 frameCount() const; atUint32 frameCount() const;
std::vector<SpriteFrame*> frames() const; std::vector<SpriteFrame*> frames() const;
SpriteFile* container() const; SpriteFile* container() const;
void setCurrentFrame(SpriteFrame* frame); void setCurrentFrame(SpriteFrame* frame);
void setCurrentFrame(atUint32 id); void setCurrentFrame(atUint32 id);
SpriteFrame* currentFrame() const; SpriteFrame* currentFrame() const;
void advanceFrame(); void advanceFrame();
void retreatFrame(); void retreatFrame();
void setRoot(SpriteFile* root);
SpriteFile* root() const;
void setRoot(SpriteFile* root);
SpriteFile* root() const;
private: private:
SpriteFile* m_root; SpriteFile* m_root;
std::string m_name; std::string m_name;
Vector2Df m_position; Vector2Df m_position;
std::vector<int> m_stateIds; //!< Stores the texture id's for each state. std::vector<int> m_stateIds; //!< Stores the texture id's for each state.
std::vector<SpriteFrame*> m_frames; std::vector<SpriteFrame*> m_frames;
atUint32 m_currentState; atUint32 m_currentState;
atUint32 m_currentFrame; atUint32 m_currentFrame;
}; };
} // zelda } // namespace athena::Sakura

View File

@ -7,74 +7,71 @@
#include <string> #include <string>
#include "athena/SakuraGlobal.hpp" #include "athena/SakuraGlobal.hpp"
namespace athena::Sakura namespace athena::Sakura {
{ struct STexture {
struct STexture std::string Filepath;
{ bool Preload;
std::string Filepath;
bool Preload;
}; };
class Sprite; class Sprite;
class SpriteFile class SpriteFile {
{
public: public:
/*! /*!
* \brief Major * \brief Major
*/ */
static const atUint32 Major; static const atUint32 Major;
/*! /*!
* \brief Minor * \brief Minor
*/ */
static const atUint32 Minor; static const atUint32 Minor;
/*! /*!
* \brief Revision * \brief Revision
*/ */
static const atUint32 Revision; static const atUint32 Revision;
/*! /*!
* \brief Patch * \brief Patch
*/ */
static const atUint32 Build; static const atUint32 Build;
/*! /*!
* \brief Version * \brief Version
*/ */
static const atUint32 Version; static const atUint32 Version;
/*! /*!
* \brief Magic * \brief Magic
*/ */
static const atUint32 Magic; static const atUint32 Magic;
/*! /*!
* \brief SSprite * \brief SSprite
*/ */
SpriteFile(); SpriteFile();
/*! /*!
* \brief SSpriteFile * \brief SSpriteFile
* \param width * \param width
* \param height * \param height
* \param originX * \param originX
* \param originY * \param originY
*/ */
SpriteFile(atUint32 width, atUint32 height, float originX, float originY); SpriteFile(atUint32 width, atUint32 height, float originX, float originY);
/*! /*!
* \brief SSpriteFile * \brief SSpriteFile
* \param size * \param size
* \param origin * \param origin
*/ */
#ifndef ATHENA_USE_QT #ifndef ATHENA_USE_QT
SpriteFile(const Vector2Di& size, const Vector2Df& origin); SpriteFile(const Vector2Di& size, const Vector2Df& origin);
#else #else
SpriteFile(const QSize& size, const QPoint& origin); SpriteFile(const QSize& size, const QPoint& origin);
#endif #endif
~SpriteFile(); ~SpriteFile();
#ifndef ATHENA_USE_QT #ifndef ATHENA_USE_QT
public: public:
@ -82,113 +79,112 @@ public:
public slots: public slots:
#endif #endif
/*! /*!
* \brief setSize * \brief setSize
* \param width * \param width
* \param height * \param height
*/ */
void setSize(atUint32 width, atUint32 height); void setSize(atUint32 width, atUint32 height);
/*! /*!
* \brief setSize * \brief setSize
* \param size * \param size
*/ */
void setSize(const Vector2Di& size); void setSize(const Vector2Di& size);
/*! /*!
* \brief size * \brief size
* \return * \return
*/ */
Vector2Di size() const; Vector2Di size() const;
/*! /*!
* \brief width * \brief width
* \return * \return
*/ */
atUint32 width() const; atUint32 width() const;
/*! /*!
* \brief height * \brief height
* \return * \return
*/ */
atUint32 height() const; atUint32 height() const;
/*! /*!
* \brief setOrigin * \brief setOrigin
* \param x * \param x
* \param y * \param y
*/ */
void setOrigin(const float x, const float y); void setOrigin(const float x, const float y);
/*! /*!
* \brief setOrigin * \brief setOrigin
* \param origin * \param origin
*/ */
void setOrigin(const Vector2Df& origin); void setOrigin(const Vector2Df& origin);
/*! /*!
* \brief origin * \brief origin
* \return * \return
*/ */
Vector2Df origin() const; Vector2Df origin() const;
/*!
* \brief originX
* \return
*/
float originX() const;
/*! /*!
* \brief originX * \brief originY
* \return * \return
*/ */
float originX() const; float originY() const;
/*! /*!
* \brief originY * \brief addTexture
* \return * \param texture
*/ */
float originY() const; bool addTexture(STexture* texture);
/*! /*!
* \brief addTexture * \brief removeTexture
* \param texture * \param id
*/ */
bool addTexture(STexture* texture); void removeTexture(int id);
/*! /*!
* \brief removeTexture * \brief texture
* \param id * \param id
*/ * \return
void removeTexture(int id); */
STexture* texture(atUint32 id);
std::vector<STexture*> textures() const;
/*! atUint32 textureCount() const;
* \brief texture /*!
* \param id * \brief setTextures
* \return * \param textures
*/ */
STexture* texture(atUint32 id); void setTextures(std::vector<STexture*> textures);
std::vector<STexture*> textures() const;
atUint32 textureCount() const; void addSprite(Sprite* sprite);
/*!
* \brief setTextures
* \param textures
*/
void setTextures(std::vector<STexture*> textures);
void addSprite(Sprite* sprite); void removeSprite(const std::string& name);
void removeSprite(Sprite* sprite);
void removeSprite(const std::string& name); void setSprites(std::unordered_map<std::string, Sprite*> sprites);
void removeSprite(Sprite* sprite); Sprite* sprite(const std::string& name);
std::unordered_map<std::string, Sprite*> sprites() const;
void setSprites(std::unordered_map<std::string, Sprite*> sprites); atUint32 spriteCount() const;
Sprite* sprite(const std::string& name);
std::unordered_map<std::string, Sprite*> sprites() const;
atUint32 spriteCount() const;
private: private:
std::vector<STexture*> m_textures; std::vector<STexture*> m_textures;
Vector2Di m_size; Vector2Di m_size;
Vector2Df m_origin; Vector2Df m_origin;
std::unordered_map<std::string, Sprite*> m_sprites; std::unordered_map<std::string, Sprite*> m_sprites;
}; };
} // Zelda } // namespace athena::Sakura
#endif // SSPRITE_HPP #endif // SSPRITE_HPP

View File

@ -2,25 +2,19 @@
#include "athena/MemoryReader.hpp" #include "athena/MemoryReader.hpp"
namespace athena::Sakura namespace athena::Sakura {
{
class SpriteFile; class SpriteFile;
} // Sakura } // namespace athena::Sakura
namespace athena namespace athena {
{ namespace io {
namespace io
{
class SpriteFileReader : public MemoryCopyReader class SpriteFileReader : public MemoryCopyReader {
{
public: public:
SpriteFileReader(atUint8* data, atUint64 length); SpriteFileReader(atUint8* data, atUint64 length);
SpriteFileReader(const std::string& filepath); SpriteFileReader(const std::string& filepath);
Sakura::SpriteFile* readFile(); Sakura::SpriteFile* readFile();
}; };
} } // namespace io
} // zelda } // namespace athena

View File

@ -2,25 +2,21 @@
#include "athena/MemoryWriter.hpp" #include "athena/MemoryWriter.hpp"
namespace athena namespace athena {
{ namespace Sakura {
namespace Sakura
{
class SpriteFile; class SpriteFile;
} // Sakura } // namespace Sakura
namespace io namespace io {
{
class SpriteFileWriter : public MemoryCopyWriter class SpriteFileWriter : public MemoryCopyWriter {
{
public: public:
SpriteFileWriter(atUint8* data, atUint64 length); SpriteFileWriter(atUint8* data, atUint64 length);
SpriteFileWriter(std::string_view filepath); SpriteFileWriter(std::string_view filepath);
void writeFile(Sakura::SpriteFile* file); void writeFile(Sakura::SpriteFile* file);
}; };
} // io } // namespace io
} // zelda } // namespace athena

View File

@ -1,49 +1,45 @@
#pragma once #pragma once
#include "athena/SakuraGlobal.hpp" #include "athena/SakuraGlobal.hpp"
#include <vector> #include <vector>
namespace athena::Sakura namespace athena::Sakura {
{
class Sprite; class Sprite;
class SpritePart; class SpritePart;
class SpriteFrame class SpriteFrame {
{
public: public:
/*! /*!
* \brief SSpriteFrame * \brief SSpriteFrame
*/ */
SpriteFrame(); SpriteFrame();
SpriteFrame(Sprite* root); SpriteFrame(Sprite* root);
/*! /*!
* \brief setFrameTime * \brief setFrameTime
* \param frameTime * \param frameTime
*/ */
void setFrameTime(float frameTime); void setFrameTime(float frameTime);
/*!
* \brief frameTime
* \return
*/
float frameTime() const;
/*! void setParts(std::vector<SpritePart*> parts);
* \brief frameTime std::vector<SpritePart*> parts() const;
* \return
*/
float frameTime() const;
void setParts(std::vector<SpritePart*> parts); atUint32 partCount() const;
std::vector<SpritePart*> parts() const;
atUint32 partCount() const; void setRoot(Sprite* root);
Sprite* root() const;
void setRoot(Sprite* root);
Sprite* root() const;
private: private:
Sprite* m_root; Sprite* m_root;
float m_frameTime; float m_frameTime;
std::vector<SpritePart*> m_parts; std::vector<SpritePart*> m_parts;
}; };
} // zelda } // namespace athena::Sakura

View File

@ -5,110 +5,106 @@
#include <string> #include <string>
namespace athena::Sakura namespace athena::Sakura {
{
class SpriteFrame; class SpriteFrame;
class SpritePart class SpritePart {
{
public: public:
SpritePart(SpriteFrame* root); SpritePart(SpriteFrame* root);
SpritePart(SpriteFrame* root, const std::string& name, bool hasCollision = false); SpritePart(SpriteFrame* root, const std::string& name, bool hasCollision = false);
virtual ~SpritePart(); virtual ~SpritePart();
void setName(const std::string& name); void setName(const std::string& name);
std::string name() const; std::string name() const;
void setCollision(bool col); void setCollision(bool col);
bool hasCollision() const; bool hasCollision() const;
/*! /*!
* \brief setOffset * \brief setOffset
* \param x * \param x
* \param y * \param y
*/ */
void setOffset(float x, float y); void setOffset(float x, float y);
void setOffset(const Vector2Df& offset); void setOffset(const Vector2Df& offset);
/*! /*!
* \brief offset * \brief offset
* \return * \return
*/ */
Vector2Df offset() const; Vector2Df offset() const;
/*! /*!
* \brief setTextureOffset * \brief setTextureOffset
* \param x * \param x
* \param y * \param y
*/ */
void setTextureOffset(float x, float y); void setTextureOffset(float x, float y);
/*! /*!
* \brief setTextureOffset * \brief setTextureOffset
* \param texOff * \param texOff
*/ */
void setTextureOffset(const Vector2Df& offset); void setTextureOffset(const Vector2Df& offset);
/*! /*!
* \brief textureOffset * \brief textureOffset
* \return * \return
*/ */
Vector2Df textureOffset() const; Vector2Df textureOffset() const;
/*! /*!
* \brief setSize * \brief setSize
* \param width * \param width
* \param height * \param height
*/ */
void setSize(atUint32 width, atUint32 height); void setSize(atUint32 width, atUint32 height);
/*! /*!
* \brief setSize * \brief setSize
* \param size * \param size
*/ */
void setSize(const Vector2Di& size); void setSize(const Vector2Di& size);
/*! /*!
* \brief size * \brief size
* \return * \return
*/ */
Vector2Di size() const; Vector2Di size() const;
/*! /*!
* \brief setFlippedHorizontally * \brief setFlippedHorizontally
* \param val * \param val
*/ */
void setFlippedHorizontally(const bool val); void setFlippedHorizontally(const bool val);
/*! /*!
* \brief flippedHorizontally * \brief flippedHorizontally
* \return * \return
*/ */
bool flippedHorizontally() const; bool flippedHorizontally() const;
/*! /*!
* \brief setFlippedVertically * \brief setFlippedVertically
* \param val * \param val
*/ */
void setFlippedVertically(const bool val); void setFlippedVertically(const bool val);
/*! /*!
* \brief flippedVertically * \brief flippedVertically
* \return * \return
*/ */
bool flippedVertically() const; bool flippedVertically() const;
void setRoot(SpriteFrame* root);
SpriteFrame* root() const;
void setRoot(SpriteFrame* root);
SpriteFrame* root() const;
private: private:
SpriteFrame* m_root; SpriteFrame* m_root;
std::string m_name; std::string m_name;
bool m_hasCollision; bool m_hasCollision;
Vector2Df m_offset; Vector2Df m_offset;
Vector2Df m_textureOffset; Vector2Df m_textureOffset;
Vector2Di m_size; Vector2Di m_size;
bool m_flippedH; bool m_flippedH;
bool m_flippedV; bool m_flippedV;
atUint32 m_frameIndex; atUint32 m_frameIndex;
}; };
} } // namespace athena::Sakura

View File

@ -13,23 +13,34 @@ using atUint64 = uint64_t;
// Vector types // Vector types
#include "simd/simd.hpp" #include "simd/simd.hpp"
typedef struct { athena::simd<float> simd; } atVec2f; typedef struct {
typedef struct { athena::simd<float> simd; } atVec3f; athena::simd<float> simd;
typedef struct { athena::simd<float> simd; } atVec4f; } atVec2f;
typedef struct { athena::simd<double> simd; } atVec2d; typedef struct {
typedef struct { athena::simd<double> simd; } atVec3d; athena::simd<float> simd;
typedef struct { athena::simd<double> simd; } atVec4d; } atVec3f;
typedef struct {
athena::simd<float> simd;
} atVec4f;
typedef struct {
athena::simd<double> simd;
} atVec2d;
typedef struct {
athena::simd<double> simd;
} atVec3d;
typedef struct {
athena::simd<double> simd;
} atVec4d;
#ifndef UNUSED #ifndef UNUSED
#define UNUSED(x) ((void)x) #define UNUSED(x) ((void)x)
#endif // UNUSED #endif // UNUSED
#ifdef __GNUC__ #ifdef __GNUC__
#define DEPRECATED(func) func __attribute__ ((deprecated)) #define DEPRECATED(func) func __attribute__((deprecated))
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
#define DEPRECATED(func) __declspec(deprecated) func #define DEPRECATED(func) __declspec(deprecated) func
#else #else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler") #pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED(func) func #define DEPRECATED(func) func
#endif #endif

View File

@ -9,190 +9,165 @@
#include "athena/Global.hpp" #include "athena/Global.hpp"
#include "athena/Types.hpp" #include "athena/Types.hpp"
namespace athena::utility namespace athena::utility {
{ inline bool isEmpty(atInt8* buf, atUint32 size) { return !memcmp(buf, buf + 1, size - 1); }
inline bool isEmpty(atInt8* buf, atUint32 size) {return !memcmp(buf, buf + 1, size - 1);}
#if _WIN32 #if _WIN32
constexpr bool isSystemBigEndian() {return false;} constexpr bool isSystemBigEndian() { return false; }
#else #else
constexpr bool isSystemBigEndian() {return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;} constexpr bool isSystemBigEndian() { return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; }
#endif #endif
inline constexpr ::athena::Endian SystemEndian = isSystemBigEndian() ? Big : Little; inline constexpr ::athena::Endian SystemEndian = isSystemBigEndian() ? Big : Little;
inline constexpr ::athena::Endian NotSystemEndian = isSystemBigEndian() ? Little : Big; inline constexpr ::athena::Endian NotSystemEndian = isSystemBigEndian() ? Little : Big;
inline atInt16 swap16(atInt16 val) inline atInt16 swap16(atInt16 val) {
{
#if __GNUC__ #if __GNUC__
return __builtin_bswap16(val); return __builtin_bswap16(val);
#elif _WIN32 #elif _WIN32
return _byteswap_ushort(val); return _byteswap_ushort(val);
#else #else
return (val = (val << 8) | ((val >> 8) & 0xFF)); return (val = (val << 8) | ((val >> 8) & 0xFF));
#endif #endif
} }
inline atUint16 swapU16(atUint16 val) {return (atUint16)swap16(val);} inline atUint16 swapU16(atUint16 val) { return (atUint16)swap16(val); }
inline atInt32 swap32(atInt32 val) inline atInt32 swap32(atInt32 val) {
{
#if __GNUC__ #if __GNUC__
return __builtin_bswap32(val); return __builtin_bswap32(val);
#elif _WIN32 #elif _WIN32
return _byteswap_ulong(val); return _byteswap_ulong(val);
#else #else
val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16; val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8; val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8;
return val; return val;
#endif #endif
} }
inline atUint32 swapU32(atUint32 val) {return (atUint32)swap32(val);} inline atUint32 swapU32(atUint32 val) { return (atUint32)swap32(val); }
inline atInt64 swap64(atInt64 val) inline atInt64 swap64(atInt64 val) {
{
#if __GNUC__ #if __GNUC__
return __builtin_bswap64(val); return __builtin_bswap64(val);
#elif _WIN32 #elif _WIN32
return _byteswap_uint64(val); return _byteswap_uint64(val);
#else #else
return (val = ((atInt64)((((atInt64)(val) & 0xFF00000000000000ULL) >> 56) | return (val = ((atInt64)(
(((atInt64)(val) & 0x00FF000000000000ULL) >> 40) | (((atInt64)(val)&0xFF00000000000000ULL) >> 56) | (((atInt64)(val)&0x00FF000000000000ULL) >> 40) |
(((atInt64)(val) & 0x0000FF0000000000ULL) >> 24) | (((atInt64)(val)&0x0000FF0000000000ULL) >> 24) | (((atInt64)(val)&0x000000FF00000000ULL) >> 8) |
(((atInt64)(val) & 0x000000FF00000000ULL) >> 8) | (((atInt64)(val)&0x00000000FF000000ULL) << 8) | (((atInt64)(val)&0x0000000000FF0000ULL) << 24) |
(((atInt64)(val) & 0x00000000FF000000ULL) << 8) | (((atInt64)(val)&0x000000000000FF00ULL) << 40) | (((atInt64)(val)&0x00000000000000FFULL) << 56))));
(((atInt64)(val) & 0x0000000000FF0000ULL) << 24) |
(((atInt64)(val) & 0x000000000000FF00ULL) << 40) |
(((atInt64)(val) & 0x00000000000000FFULL) << 56))));
#endif #endif
} }
inline atUint64 swapU64(atUint64 val) {return (atUint64)swap64(val);} inline atUint64 swapU64(atUint64 val) { return (atUint64)swap64(val); }
inline float swapFloat(float val) inline float swapFloat(float val) {
{ atInt32 ival = swap32(*((atInt32*)(&val)));
atInt32 ival = swap32(*((atInt32*)(&val))); return *((float*)(&ival));
return *((float*)(&ival));
} }
inline double swapDouble(double val) inline double swapDouble(double val) {
{ atInt64 ival = swap64(*((atInt64*)(&val)));
atInt64 ival = swap64(*((atInt64*)(&val))); return *((double*)(&ival));
return *((double*)(&ival));
} }
inline atInt16 LittleInt16(atInt16& val) inline atInt16 LittleInt16(atInt16& val) {
{ if (athena::utility::isSystemBigEndian())
if (athena::utility::isSystemBigEndian()) val = athena::utility::swap16(val);
val = athena::utility::swap16(val);
return val; return val;
} }
inline atUint16 LittleUint16(atUint16& val) inline atUint16 LittleUint16(atUint16& val) {
{ atInt16 ret = val;
atInt16 ret = val; LittleInt16(ret);
LittleInt16(ret); val = ret;
val = ret;
return val; return val;
} }
inline atInt16 BigInt16(atInt16& val) inline atInt16 BigInt16(atInt16& val) {
{ if (!athena::utility::isSystemBigEndian())
if (!athena::utility::isSystemBigEndian()) val = athena::utility::swap16(val);
val = athena::utility::swap16(val);
return val; return val;
} }
inline atUint16 BigUint16(atUint16& val) inline atUint16 BigUint16(atUint16& val) {
{ atInt16 ret = val;
atInt16 ret = val; BigInt16(ret);
BigInt16(ret); val = ret;
val = ret;
return val; return val;
} }
inline atInt32 LittleInt32(atInt32& val) inline atInt32 LittleInt32(atInt32& val) {
{ if (athena::utility::isSystemBigEndian())
if (athena::utility::isSystemBigEndian()) val = athena::utility::swap32(val);
val = athena::utility::swap32(val);
return val; return val;
} }
inline atUint32 LittleUint32(atUint32& val) inline atUint32 LittleUint32(atUint32& val) {
{ atInt32 ret = val;
atInt32 ret = val; LittleInt32(ret);
LittleInt32(ret); val = ret;
val = ret;
return val; return val;
} }
inline atInt32 BigInt32(atInt32& val) inline atInt32 BigInt32(atInt32& val) {
{ if (!athena::utility::isSystemBigEndian())
if (!athena::utility::isSystemBigEndian()) val = athena::utility::swap32(val);
val = athena::utility::swap32(val);
return val; return val;
} }
inline atUint32 BigUint32(atUint32& val) inline atUint32 BigUint32(atUint32& val) {
{ atInt32 ret = val;
atInt32 ret = val; BigInt32(ret);
BigInt32(ret); val = ret;
val = ret;
return val; return val;
} }
inline atInt64 LittleInt64(atInt64& val) inline atInt64 LittleInt64(atInt64& val) {
{ if (athena::utility::isSystemBigEndian())
if (athena::utility::isSystemBigEndian()) val = athena::utility::swap64(val);
val = athena::utility::swap64(val);
return val; return val;
} }
inline atUint64 LittleUint64(atUint64& val) inline atUint64 LittleUint64(atUint64& val) {
{ atInt64 ret = val;
atInt64 ret = val; LittleInt64(ret);
LittleInt64(ret); val = ret;
val = ret;
return val; return val;
} }
inline atInt64 BigInt64(atInt64& val) inline atInt64 BigInt64(atInt64& val) {
{ if (!athena::utility::isSystemBigEndian())
if (!athena::utility::isSystemBigEndian()) val = athena::utility::swap64(val);
val = athena::utility::swap64(val);
return val; return val;
} }
inline atUint64 BigUint64(atUint64& val) inline atUint64 BigUint64(atUint64& val) {
{ atInt64 ret = val;
atInt64 ret = val; BigInt64(ret);
BigInt64(ret); val = ret;
val = ret;
return val; return val;
} }
inline float LittleFloat(float val) inline float LittleFloat(float val) {
{ if (athena::utility::isSystemBigEndian())
if (athena::utility::isSystemBigEndian()) val = athena::utility::swapFloat(val);
val = athena::utility::swapFloat(val);
return val; return val;
} }
inline float BigFloat(float val) inline float BigFloat(float val) {
{ if (!athena::utility::isSystemBigEndian())
if (!athena::utility::isSystemBigEndian()) val = athena::utility::swapFloat(val);
val = athena::utility::swapFloat(val);
return val; return val;
} }
inline double LittleDouble(double val) inline double LittleDouble(double val) {
{ if (athena::utility::isSystemBigEndian())
if (athena::utility::isSystemBigEndian()) val = athena::utility::swapDouble(val);
val = athena::utility::swapDouble(val);
return val; return val;
} }
inline double BigDouble(double val) inline double BigDouble(double val) {
{ if (!athena::utility::isSystemBigEndian())
if (!athena::utility::isSystemBigEndian()) val = athena::utility::swapDouble(val);
val = athena::utility::swapDouble(val);
return val; return val;
} }
void fillRandom(atUint8 * rndArea, atUint64 count); void fillRandom(atUint8* rndArea, atUint64 count);
std::vector<std::string> split(std::string_view s, char delim); std::vector<std::string> split(std::string_view s, char delim);
atUint64 rand64(); atUint64 rand64();
std::string join(const std::vector<std::string>& elems, std::string_view delims); std::string join(const std::vector<std::string>& elems, std::string_view delims);
@ -221,5 +196,5 @@ std::string wideToUtf8(std::wstring_view src);
std::wstring utf8ToWide(std::string_view src); std::wstring utf8ToWide(std::string_view src);
} // Athena } // namespace athena::utility
#endif #endif

View File

@ -6,8 +6,7 @@
#include <vector> #include <vector>
#include "athena/IStreamWriter.hpp" #include "athena/IStreamWriter.hpp"
namespace athena::io namespace athena::io {
{
/*! @class VectorWriter /*! @class VectorWriter
* @brief A Stream class for writing data to a STL vector * @brief A Stream class for writing data to a STL vector
@ -16,46 +15,44 @@ namespace athena::io
* all work is done using a std::vector, and not written directly to the disk * all work is done using a std::vector, and not written directly to the disk
* @sa Stream * @sa Stream
*/ */
class VectorWriter : public IStreamWriter class VectorWriter : public IStreamWriter {
{
public: public:
/*! @brief Sets the buffers position relative to the specified position.<br /> /*! @brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default. * It seeks relative to the current position by default.
* @param position where in the buffer to seek * @param position where in the buffer to seek
* @param origin The Origin to seek @sa SeekOrigin * @param origin The Origin to seek @sa SeekOrigin
*/ */
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! @brief Returns the current position in the stream. /*! @brief Returns the current position in the stream.
* *
* @return Int64 The current position in the stream. * @return Int64 The current position in the stream.
*/ */
inline atUint64 position() const { return m_position; } inline atUint64 position() const { return m_position; }
/*! @brief Returns the length of the stream. /*! @brief Returns the length of the stream.
* *
* @return Int64 The length of the stream. * @return Int64 The length of the stream.
*/ */
inline atUint64 length() const { return m_data.size(); } inline atUint64 length() const { return m_data.size(); }
inline bool isOpen() const { return true; } inline bool isOpen() const { return true; }
/*! @brief Obtains reference to underlying std::vector store */ /*! @brief Obtains reference to underlying std::vector store */
const std::vector<uint8_t>& data() const { return m_data; } const std::vector<uint8_t>& data() const { return m_data; }
/*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length /*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length
* however it's undefined behavior to try and write a buffer which is smaller than the given length. * however it's undefined behavior to try and write a buffer which is smaller than the given length.
* If you are needing to fill in an area please use IStreamWriter::fill(atUint64) instead. * If you are needing to fill in an area please use IStreamWriter::fill(atUint64) instead.
* *
* @param data The buffer to write * @param data The buffer to write
* @param length The amount to write * @param length The amount to write
*/ */
void writeUBytes(const atUint8* data, atUint64 len); void writeUBytes(const atUint8* data, atUint64 len);
protected: protected:
std::vector<uint8_t> m_data; std::vector<uint8_t> m_data;
atUint64 m_position = 0; atUint64 m_position = 0;
}; };
} } // namespace athena::io

View File

@ -4,172 +4,165 @@
#include <string> #include <string>
#include "athena/Global.hpp" #include "athena/Global.hpp"
namespace athena namespace athena {
{
class WiiImage; class WiiImage;
/*! \class WiiBanner /*! \class WiiBanner
* \brief Wii banner container class * \brief Wii banner container class
* *
* Contains all relevant data for a Wii banner. * Contains all relevant data for a Wii banner.
*/ */
class WiiBanner class WiiBanner {
{
public: public:
enum enum { NoCopy = 0x00000001, Bounce = 0x00000010, NoCopyBounce = NoCopy | Bounce };
{
NoCopy = 0x00000001,
Bounce = 0x00000010,
NoCopyBounce = NoCopy | Bounce
};
/*! /*!
* \brief WiiBanner * \brief WiiBanner
*/ */
WiiBanner(); WiiBanner();
/*! /*!
* \brief WiiBanner * \brief WiiBanner
* \param gameId * \param gameId
* \param title * \param title
* \param subtitle * \param subtitle
* \param m_banner * \param m_banner
* \param icons * \param icons
*/ */
WiiBanner(atUint32 gameId, const std::u16string& title, const std::u16string& subtitle, WiiBanner(atUint32 gameId, const std::u16string& title, const std::u16string& subtitle, WiiImage* m_banner,
WiiImage* m_banner, std::vector<WiiImage*> icons); std::vector<WiiImage*> icons);
virtual ~WiiBanner(); virtual ~WiiBanner();
/*! /*!
* \brief setGameID * \brief setGameID
* \param id * \param id
*/ */
void setGameID(atUint64 id); void setGameID(atUint64 id);
/*! /*!
* \brief gameID * \brief gameID
* \return * \return
*/ */
atUint64 gameID() const; atUint64 gameID() const;
/*! /*!
* \brief setBannerImage * \brief setBannerImage
* \param banner * \param banner
*/ */
void setBannerImage(WiiImage* banner); void setBannerImage(WiiImage* banner);
/*! /*!
* \brief bannerImage * \brief bannerImage
* \return * \return
*/ */
WiiImage* bannerImage() const; WiiImage* bannerImage() const;
/*! /*!
* \brief setBannerSize * \brief setBannerSize
* \param size * \param size
*/ */
void setBannerSize(atUint32 size); void setBannerSize(atUint32 size);
/*! /*!
* \brief bannerSize * \brief bannerSize
* \return * \return
*/ */
atUint32 bannerSize() const; atUint32 bannerSize() const;
/*! /*!
* \brief setTitle * \brief setTitle
* \param title * \param title
*/ */
void setTitle(const std::u16string& title); void setTitle(const std::u16string& title);
/*! /*!
* \brief title * \brief title
* \return * \return
*/ */
const std::u16string& title() const; const std::u16string& title() const;
/*! /*!
* \brief setSubtitle * \brief setSubtitle
* \param subtitle * \param subtitle
*/ */
void setSubtitle(const std::u16string& subtitle); void setSubtitle(const std::u16string& subtitle);
/*! /*!
* \brief subtitle * \brief subtitle
* \return * \return
*/ */
const std::u16string& subtitle() const; const std::u16string& subtitle() const;
/*! /*!
* \brief addIcon * \brief addIcon
* \param icon * \param icon
*/ */
void addIcon(WiiImage* icon); void addIcon(WiiImage* icon);
/*! /*!
* \brief setIcon * \brief setIcon
* \param id * \param id
* \param icon * \param icon
*/ */
void setIcon(atUint32 id, WiiImage* icon); void setIcon(atUint32 id, WiiImage* icon);
/*! /*!
* \brief getIcon * \brief getIcon
* \param id * \param id
* \return * \return
*/ */
WiiImage* getIcon(atUint32 id) const; WiiImage* getIcon(atUint32 id) const;
/*! /*!
* \brief icons * \brief icons
* \return * \return
*/ */
std::vector<WiiImage*> icons() const; std::vector<WiiImage*> icons() const;
/*! /*!
* \brief setAnimationSpeed * \brief setAnimationSpeed
* \param animSpeed * \param animSpeed
*/ */
void setAnimationSpeed(atUint16 animSpeed); void setAnimationSpeed(atUint16 animSpeed);
/*! /*!
* \brief animationSpeed * \brief animationSpeed
* \return * \return
*/ */
atUint16 animationSpeed() const; atUint16 animationSpeed() const;
/*! /*!
* \brief setPermissions * \brief setPermissions
* \param permissions * \param permissions
*/ */
void setPermissions(atUint8 permissions); void setPermissions(atUint8 permissions);
/*! /*!
* \brief permissions * \brief permissions
* \return * \return
*/ */
atUint8 permissions() const; atUint8 permissions() const;
/*! /*!
* \brief setFlags * \brief setFlags
* \param flags * \param flags
*/ */
void setFlags(atUint32 flags); void setFlags(atUint32 flags);
/*!
* \brief flags
* \return
*/
atUint32 flags() const;
/*!
* \brief flags
* \return
*/
atUint32 flags() const;
protected: protected:
private: private:
atUint64 m_gameId; atUint64 m_gameId;
WiiImage* m_banner; WiiImage* m_banner;
atUint32 m_animSpeed; atUint32 m_animSpeed;
atUint8 m_permissions; atUint8 m_permissions;
atUint32 m_flags; atUint32 m_flags;
atUint32 m_bannerSize; atUint32 m_bannerSize;
std::vector<WiiImage*> m_icons; std::vector<WiiImage*> m_icons;
std::u16string m_title; std::u16string m_title;
std::u16string m_subtitle; std::u16string m_subtitle;
}; };
} // zelda } // namespace athena

View File

@ -5,217 +5,213 @@
#include <vector> #include <vector>
#include "athena/Global.hpp" #include "athena/Global.hpp"
namespace athena namespace athena {
{
const atUint8 SD_KEY [16] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08, 0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d}; const atUint8 SD_KEY[16] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08,
const atUint8 SD_IV [16] = {0x21, 0x67, 0x12, 0xe6, 0xaa, 0x1f, 0x68, 0x9f, 0x95, 0xc5, 0xa2, 0x23, 0x24, 0xdc, 0x6a, 0x98}; 0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d};
const atUint8 MD5_BLANKER[16] = {0x0e, 0x65, 0x37, 0x81, 0x99, 0xbe, 0x45, 0x17, 0xab, 0x06, 0xec, 0x22, 0x45, 0x1a, 0x57, 0x93}; const atUint8 SD_IV[16] = {0x21, 0x67, 0x12, 0xe6, 0xaa, 0x1f, 0x68, 0x9f,
0x95, 0xc5, 0xa2, 0x23, 0x24, 0xdc, 0x6a, 0x98};
const atUint8 MD5_BLANKER[16] = {0x0e, 0x65, 0x37, 0x81, 0x99, 0xbe, 0x45, 0x17,
0xab, 0x06, 0xec, 0x22, 0x45, 0x1a, 0x57, 0x93};
/*! \class WiiFile /*! \class WiiFile
* \brief Wii file container class * \brief Wii file container class
* *
* Contains all relevant data for a file in a data.bin file. * Contains all relevant data for a file in a data.bin file.
*/ */
class WiiFile class WiiFile {
{
public: public:
/*! \enum Permission
* \brief The Wii uses a bastardized unix permissions system so these flags
* reflect the file's individual permissions.
*/
enum Permission {
OtherRead = 0x01,
OtherWrite = 0x02,
GroupRead = 0x04,
GroupWrite = 0x08,
OwnerRead = 0x10,
OwnerWrite = 0x20,
/*! \enum Permission // Mask values;
* \brief The Wii uses a bastardized unix permissions system so these flags OtherRW = (OtherRead | OtherWrite), //!< Mask to get the Other group permissions
* reflect the file's individual permissions. GroupRW = (GroupRead | GroupWrite),
*/ OwnerRW = (OwnerRead | OwnerWrite)
enum Permission };
{
OtherRead = 0x01,
OtherWrite = 0x02,
GroupRead = 0x04,
GroupWrite = 0x08,
OwnerRead = 0x10,
OwnerWrite = 0x20,
// Mask values; /*!
OtherRW = (OtherRead | OtherWrite), //!< Mask to get the Other group permissions * \brief The Type enum
GroupRW = (GroupRead | GroupWrite), */
OwnerRW = (OwnerRead | OwnerWrite) enum Type { File = 0x01, Directory = 0x02 };
};
/*! WiiFile();
* \brief The Type enum
*/
enum Type
{
File = 0x01,
Directory = 0x02
};
WiiFile(); /*!
* \brief WiiFile
* \param filename
*/
WiiFile(const std::string& filename);
/*! /*!
* \brief WiiFile * \brief WiiFile
* \param filename * \param filename
*/ * \param permissions
WiiFile(const std::string& filename); * \param data
* \param length
*/
WiiFile(const std::string& filename, atUint8 permissions, const atUint8* data, atUint32 length);
virtual ~WiiFile();
/*! /*!
* \brief WiiFile * \brief setFilename
* \param filename * \param filename
* \param permissions */
* \param data void setFilename(const std::string& filename);
* \param length
*/
WiiFile(const std::string& filename, atUint8 permissions, const atUint8* data, atUint32 length);
virtual ~WiiFile();
/*! /*!
* \brief setFilename * \brief filename
* \param filename * \return
*/ */
void setFilename(const std::string& filename); std::string filename() const;
/*! /*!
* \brief filename * \brief setData
* \return * \param data
*/ */
std::string filename() const; void setData(const atUint8* data);
/*!
* \brief data
* \return
*/
atUint8* data() const;
/*! /*!
* \brief setData * \brief setLength
* \param data * \param len
*/ */
void setData(const atUint8* data); void setLength(const int len);
/*!
* \brief data
* \return
*/
atUint8* data() const;
/*! /*!
* \brief setLength * \brief length
* \param len * \return
*/ */
void setLength(const int len); int length() const;
/*! /*!
* \brief length * \brief setPermissions
* \return * \param permissions
*/ */
int length() const; void setPermissions(const atUint8 permissions);
/*! /*!
* \brief setPermissions * \brief permissions
* \param permissions * \return
*/ */
void setPermissions(const atUint8 permissions); atUint8 permissions() const;
/*! /*!
* \brief permissions * \brief setAttributes
* \return * \param attr
*/ */
atUint8 permissions() const; void setAttributes(const atUint8 attr);
/*! /*!
* \brief setAttributes * \brief attributes
* \param attr * \return
*/ */
void setAttributes(const atUint8 attr); atUint8 attributes() const;
/*! /*!
* \brief attributes * \brief setType
* \return * \param type
*/ */
atUint8 attributes() const; void setType(Type type);
/*! /*!
* \brief setType * \brief type
* \param type * \return
*/ */
void setType(Type type); Type type() const;
/*! /*!
* \brief type * \brief isDirectory
* \return * \return
*/ */
Type type() const; bool isDirectory() const;
/*! /*!
* \brief isDirectory * \brief isFile
* \return * \return
*/ */
bool isDirectory() const; bool isFile() const;
/*! /*!
* \brief isFile * \brief addChild
* \return * \param file
*/ */
bool isFile() const; void addChild(WiiFile* file);
/*!
* \brief children
* \return
*/
std::vector<WiiFile*> children();
/*!
* \brief child
* \param name
* \return
*/
WiiFile* child(const std::string& name);
/*!
* \brief removeChild
* \param name
*/
void removeChild(const std::string& name);
/*!
* \brief removeChild
* \param file
*/
void removeChild(WiiFile* file);
/*! /*!
* \brief addChild * \brief parent
* \param file * \return
*/ */
void addChild(WiiFile* file); WiiFile* parent();
/*!
* \brief children
* \return
*/
std::vector<WiiFile*> children();
/*!
* \brief child
* \param name
* \return
*/
WiiFile* child(const std::string& name);
/*!
* \brief removeChild
* \param name
*/
void removeChild(const std::string& name);
/*!
* \brief removeChild
* \param file
*/
void removeChild(WiiFile* file);
/*! /*!
* \brief parent * \brief setParent
* \return * \param parent
*/ */
WiiFile* parent(); void setParent(WiiFile* parent);
/*! /*!
* \brief setParent * \brief fileCount
* \param parent * \return
*/ */
void setParent(WiiFile* parent); atUint32 fileCount();
/*! /*!
* \brief fileCount * \brief allChildren
* \return * \return
*/ */
atUint32 fileCount(); std::vector<WiiFile*> allChildren();
/*! /*!
* \brief allChildren * \brief fullpath
* \return * \return
*/ */
std::vector<WiiFile*> allChildren(); std::string fullpath();
/*!
* \brief fullpath
* \return
*/
std::string fullpath();
protected: protected:
private: private:
atUint8 m_permissions; atUint8 m_permissions;
atUint8 m_attributes; atUint8 m_attributes;
Type m_type; Type m_type;
std::string m_filename; std::string m_filename;
int m_fileLen; int m_fileLen;
atUint8* m_fileData; atUint8* m_fileData;
WiiFile* m_parent; WiiFile* m_parent;
std::vector<WiiFile*> m_children; std::vector<WiiFile*> m_children;
}; };
} // zelda } // namespace athena

View File

@ -3,74 +3,71 @@
#include <memory> #include <memory>
#include "athena/Types.hpp" #include "athena/Types.hpp"
namespace athena namespace athena {
{
/*! /*!
* \brief The WiiImage class * \brief The WiiImage class
*/ */
class WiiImage class WiiImage {
{
public: public:
/*! /*!
* \brief WiiImage * \brief WiiImage
*/ */
WiiImage(); WiiImage();
/*! /*!
* \brief WiiImage * \brief WiiImage
* \param width * \param width
* \param height * \param height
* \param data * \param data
*/ */
WiiImage(atUint32 width, atUint32 height, std::unique_ptr<atUint8[]>&& data); WiiImage(atUint32 width, atUint32 height, std::unique_ptr<atUint8[]>&& data);
/*! /*!
* \brief setWidth * \brief setWidth
* \param width * \param width
*/ */
void setWidth(const atUint32 width); void setWidth(const atUint32 width);
/*! /*!
* \brief width * \brief width
* \return * \return
*/ */
atUint32 width() const; atUint32 width() const;
/*! /*!
* \brief setHeight * \brief setHeight
* \param height * \param height
*/ */
void setHeight(const atUint32 height); void setHeight(const atUint32 height);
/*! /*!
* \brief height * \brief height
* \return * \return
*/ */
atUint32 height() const; atUint32 height() const;
/*! /*!
* \brief setData * \brief setData
* \param data * \param data
*/ */
void setData(const atUint8* data); void setData(const atUint8* data);
/*! /*!
* \brief data * \brief data
* \return * \return
*/ */
atUint8* data(); atUint8* data();
/*! /*!
* \brief toRGBA * \brief toRGBA
* \return * \return
*/ */
atUint8* toRGBA(); atUint8* toRGBA();
private: private:
atUint32 m_width; atUint32 m_width;
atUint32 m_height; atUint32 m_height;
std::unique_ptr<atUint8[]> m_data; std::unique_ptr<atUint8[]> m_data;
}; };
} // zelda } // namespace athena

View File

@ -5,8 +5,7 @@
#include <vector> #include <vector>
#include "athena/Global.hpp" #include "athena/Global.hpp"
namespace athena namespace athena {
{
class WiiFile; class WiiFile;
class WiiBanner; class WiiBanner;
@ -19,65 +18,61 @@ class BinaryWriter;
* *
* Contains all relevant data for a Wii data.bin file. * Contains all relevant data for a Wii data.bin file.
*/ */
class WiiSave class WiiSave {
{
public: public:
/*!
* \brief FileIterator
*/
typedef std::unordered_map<std::string, WiiFile*>::const_iterator FileIterator;
/*! /*!
* \brief FileIterator * \brief WiiSave
*/ */
typedef std::unordered_map<std::string, WiiFile*>::const_iterator FileIterator; WiiSave();
/*!
* \brief ~WiiSave
*/
virtual ~WiiSave();
/*! /*!
* \brief WiiSave * \brief addFile
*/ * \param filename
WiiSave(); * \param file
/*! */
* \brief ~WiiSave void addFile(WiiFile* file);
*/ void setRoot(WiiFile* root);
virtual ~WiiSave(); /*!
* \brief file
* \param filename
* \return
*/
WiiFile* file(const std::string& filename);
/*! atUint32 fileCount() const;
* \brief addFile /*!
* \param filename * \brief fileList
* \param file * \return
*/ */
void addFile(WiiFile* file); WiiFile* root();
void setRoot(WiiFile* root);
/*!
* \brief file
* \param filename
* \return
*/
WiiFile* file(const std::string& filename);
atUint32 fileCount() const; /*!
/*! * \brief setBanner
* \brief fileList * \param banner
* \return */
*/ void setBanner(WiiBanner* banner);
WiiFile* root();
/*! /*!
* \brief setBanner * \brief banner
* \param banner * \return
*/ */
void setBanner(WiiBanner* banner); WiiBanner* banner() const;
/*! std::vector<WiiFile*> allFiles() const;
* \brief banner
* \return
*/
WiiBanner* banner() const;
std::vector<WiiFile*> allFiles() const;
protected: protected:
private: private:
WiiFile* m_root;
WiiFile* m_root; WiiBanner* m_banner;
WiiBanner* m_banner;
}; };
} // zelda } // namespace athena

View File

@ -3,15 +3,13 @@
#include "athena/Global.hpp" #include "athena/Global.hpp"
#include "athena/MemoryReader.hpp" #include "athena/MemoryReader.hpp"
namespace athena namespace athena {
{
class WiiSave; class WiiSave;
class WiiBanner; class WiiBanner;
class WiiFile; class WiiFile;
class WiiImage; class WiiImage;
namespace io namespace io {
{
/*! \class WiiSaveReader /*! \class WiiSaveReader
* \brief Wii data.bin reader class * \brief Wii data.bin reader class
@ -20,34 +18,34 @@ namespace io
* all work is done using a memory buffer, and not read directly from the disk. * all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class WiiSaveReader : public MemoryCopyReader class WiiSaveReader : public MemoryCopyReader {
{
public: public:
/*! \brief This constructor takes an existing buffer to read from. /*! \brief This constructor takes an existing buffer to read from.
* *
* \param data The existing buffer * \param data The existing buffer
* \param length The length of the existing buffer * \param length The length of the existing buffer
*/ */
WiiSaveReader(const atUint8*, atUint64); WiiSaveReader(const atUint8*, atUint64);
/*! \brief This constructor creates an instance from a file on disk. /*! \brief This constructor creates an instance from a file on disk.
* *
* \param filename The file to create the stream from * \param filename The file to create the stream from
*/ */
WiiSaveReader(const std::string&); WiiSaveReader(const std::string&);
/*!
* \brief readSave
* \return
*/
std::unique_ptr<WiiSave> readSave();
/*!
* \brief readSave
* \return
*/
std::unique_ptr<WiiSave> readSave();
private: private:
WiiBanner* readBanner(); WiiBanner* readBanner();
WiiFile* readFile(); WiiFile* readFile();
WiiImage* readImage(atUint32 width, atUint32 height); WiiImage* readImage(atUint32 width, atUint32 height);
void readCerts(atUint32 totalSize); void readCerts(atUint32 totalSize);
WiiFile* buildTree(std::vector<WiiFile*> files); WiiFile* buildTree(std::vector<WiiFile*> files);
}; };
} // io } // namespace io
} // zelda } // namespace athena

View File

@ -2,15 +2,13 @@
#include "athena/MemoryWriter.hpp" #include "athena/MemoryWriter.hpp"
namespace athena namespace athena {
{
class WiiSave; class WiiSave;
class WiiBanner; class WiiBanner;
class WiiFile; class WiiFile;
class WiiImage; class WiiImage;
namespace io namespace io {
{
/*! \class WiiSaveWriter /*! \class WiiSaveWriter
* \brief Wii data.bin writer class * \brief Wii data.bin writer class
@ -19,34 +17,34 @@ namespace io
* all work is done using a memory buffer, and not written directly to the disk. * all work is done using a memory buffer, and not written directly to the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class WiiSaveWriter : protected MemoryCopyWriter class WiiSaveWriter : protected MemoryCopyWriter {
{
public: public:
/*! \brief This constructor creates an instance from a file on disk. /*! \brief This constructor creates an instance from a file on disk.
* *
* \param filename The file to create the stream from * \param filename The file to create the stream from
*/ */
WiiSaveWriter(const std::string&); WiiSaveWriter(const std::string&);
/*! /*!
* \brief writeSave * \brief writeSave
* \param save * \param save
* \param macAddress * \param macAddress
* \param ngId * \param ngId
* \param ngPriv * \param ngPriv
* \param ngSig * \param ngSig
* \param ngKeyId * \param ngKeyId
* \param filepath * \param filepath
* \return * \return
*/ */
bool writeSave(WiiSave* save, atUint8* macAddress, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId, const std::string& filepath = ""); bool writeSave(WiiSave* save, atUint8* macAddress, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId,
const std::string& filepath = "");
private: private:
void writeBanner(WiiBanner* banner); void writeBanner(WiiBanner* banner);
atUint32 writeFile(WiiFile* file); atUint32 writeFile(WiiFile* file);
void writeImage(WiiImage* image); void writeImage(WiiImage* image);
void writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId); void writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId);
}; };
} // io } // namespace io
} // zelda } // namespace athena

View File

@ -12,157 +12,147 @@
#include <functional> #include <functional>
#include "Global.hpp" #include "Global.hpp"
namespace athena::io namespace athena::io {
{
class IStreamReader; class IStreamReader;
class IStreamWriter; class IStreamWriter;
enum class YAMLNodeStyle enum class YAMLNodeStyle { Any, Flow, Block };
{
Any, struct YAMLNode {
Flow, yaml_node_type_t m_type;
Block std::string m_scalarString;
std::vector<std::unique_ptr<YAMLNode>> m_seqChildren;
std::vector<std::pair<std::string, std::unique_ptr<YAMLNode>>> m_mapChildren;
YAMLNodeStyle m_style = YAMLNodeStyle::Any;
YAMLNode(yaml_node_type_t type) : m_type(type) {}
inline const YAMLNode* findMapChild(std::string_view key) const {
for (const auto& item : m_mapChildren)
if (!item.first.compare(key))
return item.second.get();
return nullptr;
}
inline void assignMapChild(std::string_view key, std::unique_ptr<YAMLNode>&& node) {
for (auto& item : m_mapChildren)
if (!item.first.compare(key)) {
item.second = std::move(node);
return;
}
m_mapChildren.emplace_back(key, std::move(node));
}
}; };
struct YAMLNode template <typename RETURNTYPE>
{
yaml_node_type_t m_type;
std::string m_scalarString;
std::vector<std::unique_ptr<YAMLNode>> m_seqChildren;
std::vector<std::pair<std::string, std::unique_ptr<YAMLNode>>> m_mapChildren;
YAMLNodeStyle m_style = YAMLNodeStyle::Any;
YAMLNode(yaml_node_type_t type) : m_type(type) {}
inline const YAMLNode* findMapChild(std::string_view key) const
{
for (const auto& item : m_mapChildren)
if (!item.first.compare(key))
return item.second.get();
return nullptr;
}
inline void assignMapChild(std::string_view key, std::unique_ptr <YAMLNode>&& node)
{
for (auto& item : m_mapChildren)
if (!item.first.compare(key))
{
item.second = std::move(node);
return;
}
m_mapChildren.emplace_back(key, std::move(node));
}
};
template<typename RETURNTYPE>
RETURNTYPE NodeToVal(const YAMLNode* node); RETURNTYPE NodeToVal(const YAMLNode* node);
template<> template <>
bool NodeToVal(const YAMLNode* node); bool NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(bool val); std::unique_ptr<YAMLNode> ValToNode(bool val);
template<> template <>
atInt8 NodeToVal(const YAMLNode* node); atInt8 NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(atInt8 val); std::unique_ptr<YAMLNode> ValToNode(atInt8 val);
template<> template <>
atUint8 NodeToVal(const YAMLNode* node); atUint8 NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(atUint8 val); std::unique_ptr<YAMLNode> ValToNode(atUint8 val);
template<> template <>
atInt16 NodeToVal(const YAMLNode* node); atInt16 NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(atInt16 val); std::unique_ptr<YAMLNode> ValToNode(atInt16 val);
template<> template <>
atUint16 NodeToVal(const YAMLNode* node); atUint16 NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(atUint16 val); std::unique_ptr<YAMLNode> ValToNode(atUint16 val);
template<> template <>
atInt32 NodeToVal(const YAMLNode* node); atInt32 NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(atInt32 val); std::unique_ptr<YAMLNode> ValToNode(atInt32 val);
template<> template <>
atUint32 NodeToVal(const YAMLNode* node); atUint32 NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(atUint32 val); std::unique_ptr<YAMLNode> ValToNode(atUint32 val);
template<> template <>
atInt64 NodeToVal(const YAMLNode* node); atInt64 NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(atInt64 val); std::unique_ptr<YAMLNode> ValToNode(atInt64 val);
template<> template <>
atUint64 NodeToVal(const YAMLNode* node); atUint64 NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(atUint64 val); std::unique_ptr<YAMLNode> ValToNode(atUint64 val);
template<> template <>
float NodeToVal(const YAMLNode* node); float NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(float val); std::unique_ptr<YAMLNode> ValToNode(float val);
template<> template <>
double NodeToVal(const YAMLNode* node); double NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(double val); std::unique_ptr<YAMLNode> ValToNode(double val);
template<typename RETURNTYPE> template <typename RETURNTYPE>
RETURNTYPE NodeToVec(const YAMLNode* node); RETURNTYPE NodeToVec(const YAMLNode* node);
template<> template <>
atVec2f NodeToVal(const YAMLNode* node); atVec2f NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(const atVec2f& val); std::unique_ptr<YAMLNode> ValToNode(const atVec2f& val);
template<> template <>
atVec3f NodeToVal(const YAMLNode* node); atVec3f NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(const atVec3f& val); std::unique_ptr<YAMLNode> ValToNode(const atVec3f& val);
template<> template <>
atVec4f NodeToVal(const YAMLNode* node); atVec4f NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(const atVec4f& val); std::unique_ptr<YAMLNode> ValToNode(const atVec4f& val);
template<> template <>
atVec2d NodeToVal(const YAMLNode* node); atVec2d NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(const atVec2d& val); std::unique_ptr<YAMLNode> ValToNode(const atVec2d& val);
template<> template <>
atVec3d NodeToVal(const YAMLNode* node); atVec3d NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(const atVec3d& val); std::unique_ptr<YAMLNode> ValToNode(const atVec3d& val);
template<> template <>
atVec4d NodeToVal(const YAMLNode* node); atVec4d NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(const atVec4d& val); std::unique_ptr<YAMLNode> ValToNode(const atVec4d& val);
template<> template <>
std::unique_ptr<atUint8[]> NodeToVal(const YAMLNode* node); std::unique_ptr<atUint8[]> NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(const std::unique_ptr<atUint8[]>& val, size_t byteCount); std::unique_ptr<YAMLNode> ValToNode(const std::unique_ptr<atUint8[]>& val, size_t byteCount);
template<> template <>
std::string NodeToVal(const YAMLNode* node); std::string NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(std::string_view val); std::unique_ptr<YAMLNode> ValToNode(std::string_view val);
template<> template <>
std::wstring NodeToVal(const YAMLNode* node); std::wstring NodeToVal(const YAMLNode* node);
std::unique_ptr <YAMLNode> ValToNode(std::wstring_view val); std::unique_ptr<YAMLNode> ValToNode(std::wstring_view val);
std::unique_ptr <YAMLNode> ValToNode(std::u16string_view val); std::unique_ptr<YAMLNode> ValToNode(std::u16string_view val);
std::unique_ptr <YAMLNode> ValToNode(std::u32string_view val); std::unique_ptr<YAMLNode> ValToNode(std::u32string_view val);
std::string base64_encode(const atUint8* bytes_to_encode, size_t in_len); std::string base64_encode(const atUint8* bytes_to_encode, size_t in_len);
@ -172,28 +162,22 @@ void HandleYAMLParserError(yaml_parser_t* parser);
void HandleYAMLEmitterError(yaml_emitter_t* emitter); void HandleYAMLEmitterError(yaml_emitter_t* emitter);
struct YAMLStdStringViewReaderState struct YAMLStdStringViewReaderState {
{ std::string_view::const_iterator begin;
std::string_view::const_iterator begin; std::string_view::const_iterator end;
std::string_view::const_iterator end;
YAMLStdStringViewReaderState(std::string_view str) YAMLStdStringViewReaderState(std::string_view str) {
{ begin = str.begin();
begin = str.begin(); end = str.end();
end = str.end(); }
}
}; };
int YAMLStdStringReader(YAMLStdStringViewReaderState* str, int YAMLStdStringReader(YAMLStdStringViewReaderState* str, unsigned char* buffer, size_t size, size_t* size_read);
unsigned char* buffer, size_t size, size_t* size_read);
int YAMLStdStringWriter(std::string* str, unsigned char* buffer, size_t size); int YAMLStdStringWriter(std::string* str, unsigned char* buffer, size_t size);
int YAMLAthenaReader(athena::io::IStreamReader* reader, int YAMLAthenaReader(athena::io::IStreamReader* reader, unsigned char* buffer, size_t size, size_t* size_read);
unsigned char* buffer, size_t size, size_t* size_read);
int YAMLAthenaWriter(athena::io::IStreamWriter* writer, int YAMLAthenaWriter(athena::io::IStreamWriter* writer, unsigned char* buffer, size_t size);
unsigned char* buffer, size_t size);
}
} // namespace athena::io

View File

@ -2,168 +2,160 @@
#include "YAMLCommon.hpp" #include "YAMLCommon.hpp"
namespace athena::io namespace athena::io {
{
class YAMLDocReader class YAMLDocReader {
{ std::unique_ptr<YAMLNode> m_rootNode;
std::unique_ptr<YAMLNode> m_rootNode; std::vector<YAMLNode*> m_subStack;
std::vector<YAMLNode*> m_subStack; std::vector<int> m_seqTrackerStack;
std::vector<int> m_seqTrackerStack; yaml_parser_t m_parser;
yaml_parser_t m_parser; std::unique_ptr<YAMLNode> ParseEvents(athena::io::IStreamReader* reader);
std::unique_ptr<YAMLNode> ParseEvents(athena::io::IStreamReader* reader); void _leaveSubRecord();
void _leaveSubRecord(); void _leaveSubVector();
void _leaveSubVector();
public: public:
YAMLDocReader(); YAMLDocReader();
~YAMLDocReader(); ~YAMLDocReader();
void reset(); void reset();
inline yaml_parser_t* getParser() { return &m_parser; } inline yaml_parser_t* getParser() { return &m_parser; }
bool parse(athena::io::IStreamReader* reader); bool parse(athena::io::IStreamReader* reader);
bool ClassTypeOperation(std::function<bool(const char* dnaType)> func); bool ClassTypeOperation(std::function<bool(const char* dnaType)> func);
bool ValidateClassType(const char* expectedType); bool ValidateClassType(const char* expectedType);
inline const YAMLNode* getRootNode() const { return m_rootNode.get(); } inline const YAMLNode* getRootNode() const { return m_rootNode.get(); }
inline const YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); } inline const YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); }
std::unique_ptr<YAMLNode> releaseRootNode() { return std::move(m_rootNode); } std::unique_ptr<YAMLNode> releaseRootNode() { return std::move(m_rootNode); }
class RecordRAII class RecordRAII {
{ friend class YAMLDocReader;
friend class YAMLDocReader; YAMLDocReader* m_r = nullptr;
YAMLDocReader* m_r = nullptr; RecordRAII(YAMLDocReader* r) : m_r(r) {}
RecordRAII(YAMLDocReader* r) : m_r(r) {} RecordRAII() = default;
RecordRAII() = default;
public:
operator bool() const { return m_r != nullptr; }
void leave() { if (m_r) {m_r->_leaveSubRecord(); m_r = nullptr;} }
~RecordRAII() { if (m_r) m_r->_leaveSubRecord(); }
};
friend class RecordRAII;
RecordRAII enterSubRecord(const char* name); public:
operator bool() const { return m_r != nullptr; }
template <class T> void leave() {
void enumerate(const char* name, T& record, if (m_r) {
typename std::enable_if_t<__IsDNARecord_v<T>>* = 0) m_r->_leaveSubRecord();
{ m_r = nullptr;
if (auto rec = enterSubRecord(name)) }
record.read(*this);
} }
~RecordRAII() {
class VectorRAII if (m_r)
{ m_r->_leaveSubRecord();
friend class YAMLDocReader;
YAMLDocReader* m_r = nullptr;
VectorRAII(YAMLDocReader* r) : m_r(r) {}
VectorRAII() = default;
public:
operator bool() const { return m_r != nullptr; }
~VectorRAII() { if (m_r) m_r->_leaveSubVector(); }
};
friend class VectorRAII;
VectorRAII enterSubVector(const char* name, size_t& countOut);
template <class T>
size_t enumerate(const char* name, std::vector<T>& vector,
typename std::enable_if_t<!std::is_arithmetic<T>::value &&
!std::is_same<T, atVec2f>::value &&
!std::is_same<T, atVec3f>::value &&
!std::is_same<T, atVec4f>::value>* = 0)
{
size_t countOut;
if (auto v = enterSubVector(name, countOut))
{
vector.clear();
vector.reserve(countOut);
for (size_t i=0 ; i<countOut ; ++i)
{
vector.emplace_back();
if (auto rec = enterSubRecord(nullptr))
vector.back().read(*this);
}
}
return countOut;
} }
};
friend class RecordRAII;
template <class T> RecordRAII enterSubRecord(const char* name);
size_t enumerate(const char* name, std::vector<T>& vector,
typename std::enable_if_t<std::is_arithmetic<T>::value || template <class T>
std::is_same<T, atVec2f>::value || void enumerate(const char* name, T& record, typename std::enable_if_t<__IsDNARecord_v<T>>* = 0) {
std::is_same<T, atVec3f>::value || if (auto rec = enterSubRecord(name))
std::is_same<T, atVec4f>::value>* = 0) record.read(*this);
{ }
size_t countOut;
if (auto v = enterSubVector(name, countOut)) class VectorRAII {
{ friend class YAMLDocReader;
vector.clear(); YAMLDocReader* m_r = nullptr;
vector.reserve(countOut); VectorRAII(YAMLDocReader* r) : m_r(r) {}
for (size_t i=0 ; i<countOut ; ++i) VectorRAII() = default;
vector.push_back(readVal<T>(name));
} public:
return countOut; operator bool() const { return m_r != nullptr; }
~VectorRAII() {
if (m_r)
m_r->_leaveSubVector();
} }
};
friend class VectorRAII;
template <class T> VectorRAII enterSubVector(const char* name, size_t& countOut);
size_t enumerate(const char* name, std::vector<T>& vector,
std::function<void(YAMLDocReader&, T&)> readf) template <class T>
{ size_t
size_t countOut; enumerate(const char* name, std::vector<T>& vector,
if (auto v = enterSubVector(name, countOut)) typename std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_same<T, atVec2f>::value &&
{ !std::is_same<T, atVec3f>::value && !std::is_same<T, atVec4f>::value>* = 0) {
vector.clear(); size_t countOut;
vector.reserve(countOut); if (auto v = enterSubVector(name, countOut)) {
for (size_t i=0 ; i<countOut ; ++i) vector.clear();
{ vector.reserve(countOut);
vector.emplace_back(); for (size_t i = 0; i < countOut; ++i) {
if (auto rec = enterSubRecord(nullptr)) vector.emplace_back();
readf(*this, vector.back()); if (auto rec = enterSubRecord(nullptr))
} vector.back().read(*this);
} }
return countOut;
} }
return countOut;
}
bool hasVal(const char* name) const template <class T>
{ size_t enumerate(const char* name, std::vector<T>& vector,
if (m_subStack.size()) typename std::enable_if_t<std::is_arithmetic<T>::value || std::is_same<T, atVec2f>::value ||
{ std::is_same<T, atVec3f>::value || std::is_same<T, atVec4f>::value>* = 0) {
const YAMLNode* mnode = m_subStack.back(); size_t countOut;
if (mnode->m_type == YAML_MAPPING_NODE && name) if (auto v = enterSubVector(name, countOut)) {
for (const auto& item : mnode->m_mapChildren) vector.clear();
if (!item.first.compare(name)) vector.reserve(countOut);
return true; for (size_t i = 0; i < countOut; ++i)
} vector.push_back(readVal<T>(name));
return false;
} }
return countOut;
}
template <typename RETURNTYPE> template <class T>
RETURNTYPE readVal(const char* name); size_t enumerate(const char* name, std::vector<T>& vector, std::function<void(YAMLDocReader&, T&)> readf) {
bool readBool(const char* name); size_t countOut;
atInt8 readByte(const char* name); if (auto v = enterSubVector(name, countOut)) {
atUint8 readUByte(const char* name); vector.clear();
atInt16 readInt16(const char* name); vector.reserve(countOut);
atUint16 readUint16(const char* name); for (size_t i = 0; i < countOut; ++i) {
atInt32 readInt32(const char* name); vector.emplace_back();
atUint32 readUint32(const char* name); if (auto rec = enterSubRecord(nullptr))
atInt64 readInt64(const char* name); readf(*this, vector.back());
atUint64 readUint64(const char* name); }
float readFloat(const char* name); }
double readDouble(const char* name); return countOut;
atVec2f readVec2f(const char* name); }
atVec3f readVec3f(const char* name);
atVec4f readVec4f(const char* name); bool hasVal(const char* name) const {
atVec2d readVec2d(const char* name); if (m_subStack.size()) {
atVec3d readVec3d(const char* name); const YAMLNode* mnode = m_subStack.back();
atVec4d readVec4d(const char* name); if (mnode->m_type == YAML_MAPPING_NODE && name)
std::unique_ptr<atUint8[]> readUBytes(const char* name); for (const auto& item : mnode->m_mapChildren)
std::string readString(const char* name); if (!item.first.compare(name))
std::wstring readWString(const char* name); return true;
}
return false;
}
template <typename RETURNTYPE>
RETURNTYPE readVal(const char* name);
bool readBool(const char* name);
atInt8 readByte(const char* name);
atUint8 readUByte(const char* name);
atInt16 readInt16(const char* name);
atUint16 readUint16(const char* name);
atInt32 readInt32(const char* name);
atUint32 readUint32(const char* name);
atInt64 readInt64(const char* name);
atUint64 readUint64(const char* name);
float readFloat(const char* name);
double readDouble(const char* name);
atVec2f readVec2f(const char* name);
atVec3f readVec3f(const char* name);
atVec4f readVec4f(const char* name);
atVec2d readVec2d(const char* name);
atVec3d readVec3d(const char* name);
atVec4d readVec4d(const char* name);
std::unique_ptr<atUint8[]> readUBytes(const char* name);
std::string readString(const char* name);
std::wstring readWString(const char* name);
}; };
} } // namespace athena::io

View File

@ -2,133 +2,125 @@
#include "YAMLCommon.hpp" #include "YAMLCommon.hpp"
namespace athena::io namespace athena::io {
{
class YAMLDocWriter {
std::unique_ptr<YAMLNode> m_rootNode;
std::vector<YAMLNode*> m_subStack;
yaml_emitter_t m_emitter;
static bool RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node);
void _leaveSubRecord();
void _leaveSubVector();
class YAMLDocWriter
{
std::unique_ptr<YAMLNode> m_rootNode;
std::vector<YAMLNode*> m_subStack;
yaml_emitter_t m_emitter;
static bool RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node);
void _leaveSubRecord();
void _leaveSubVector();
public: public:
YAMLDocWriter(const char* classType, athena::io::IStreamReader* reader = nullptr); YAMLDocWriter(const char* classType, athena::io::IStreamReader* reader = nullptr);
~YAMLDocWriter(); ~YAMLDocWriter();
yaml_emitter_t* getEmitter() { return &m_emitter; } yaml_emitter_t* getEmitter() { return &m_emitter; }
bool finish(athena::io::IStreamWriter* fout); bool finish(athena::io::IStreamWriter* fout);
inline YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); } inline YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); }
class RecordRAII class RecordRAII {
{ friend class YAMLDocWriter;
friend class YAMLDocWriter; YAMLDocWriter* m_w = nullptr;
YAMLDocWriter* m_w = nullptr; RecordRAII(YAMLDocWriter* w) : m_w(w) {}
RecordRAII(YAMLDocWriter* w) : m_w(w) {} RecordRAII() = default;
RecordRAII() = default;
public:
operator bool() const { return m_w != nullptr; }
~RecordRAII() { if (m_w) m_w->_leaveSubRecord(); }
};
friend class RecordRAII;
RecordRAII enterSubRecord(const char* name); public:
operator bool() const { return m_w != nullptr; }
template <class T> ~RecordRAII() {
void enumerate(const char* name, T& record, if (m_w)
typename std::enable_if_t<__IsDNARecord_v<T>>* = 0) m_w->_leaveSubRecord();
{
if (auto rec = enterSubRecord(name))
record.write(*this);
} }
};
friend class RecordRAII;
class VectorRAII RecordRAII enterSubRecord(const char* name);
{
friend class YAMLDocWriter;
YAMLDocWriter* m_w = nullptr;
VectorRAII(YAMLDocWriter* w) : m_w(w) {}
VectorRAII() = default;
public:
operator bool() const { return m_w != nullptr; }
~VectorRAII() { if (m_w) m_w->_leaveSubVector(); }
};
friend class VectorRAII;
VectorRAII enterSubVector(const char* name); template <class T>
void enumerate(const char* name, T& record, typename std::enable_if_t<__IsDNARecord_v<T>>* = 0) {
if (auto rec = enterSubRecord(name))
record.write(*this);
}
template <class T> class VectorRAII {
void enumerate(const char* name, const std::vector<T>& vector, friend class YAMLDocWriter;
typename std::enable_if_t<!std::is_arithmetic<T>::value && YAMLDocWriter* m_w = nullptr;
!std::is_same<T, atVec2f>::value && VectorRAII(YAMLDocWriter* w) : m_w(w) {}
!std::is_same<T, atVec3f>::value && VectorRAII() = default;
!std::is_same<T, atVec4f>::value &&
!std::is_same<T, atVec2d>::value && public:
!std::is_same<T, atVec3d>::value && operator bool() const { return m_w != nullptr; }
!std::is_same<T, atVec4d>::value>* = 0) ~VectorRAII() {
{ if (m_w)
if (auto v = enterSubVector(name)) m_w->_leaveSubVector();
for (const T& item : vector)
if (auto rec = enterSubRecord(nullptr))
item.write(*this);
} }
};
friend class VectorRAII;
template <class T> VectorRAII enterSubVector(const char* name);
void enumerate(const char* name, const std::vector<T>& vector,
typename std::enable_if_t<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value ||
std::is_same<T, atVec4f>::value ||
std::is_same<T, atVec2d>::value ||
std::is_same<T, atVec3d>::value ||
std::is_same<T, atVec4d>::value>* = 0)
{
if (auto v = enterSubVector(name))
for (T item : vector)
writeVal<T>(nullptr, item);
}
template <class T> template <class T>
void enumerate(const char* name, const std::vector<T>& vector, void enumerate(const char* name, const std::vector<T>& vector,
std::function<void(YAMLDocWriter&, const T&)> writef) typename std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_same<T, atVec2f>::value &&
{ !std::is_same<T, atVec3f>::value && !std::is_same<T, atVec4f>::value &&
if (auto v = enterSubVector(name)) !std::is_same<T, atVec2d>::value && !std::is_same<T, atVec3d>::value &&
for (const T& item : vector) !std::is_same<T, atVec4d>::value>* = 0) {
if (auto rec = enterSubRecord(nullptr)) if (auto v = enterSubVector(name))
writef(*this, item); for (const T& item : vector)
} if (auto rec = enterSubRecord(nullptr))
item.write(*this);
}
template <typename INTYPE> template <class T>
void writeVal(const char* name, const INTYPE& val); void enumerate(const char* name, const std::vector<T>& vector,
template <typename INTYPE> typename std::enable_if_t<std::is_arithmetic<T>::value || std::is_same<T, atVec2f>::value ||
void writeVal(const char* name, const INTYPE& val, size_t byteCount); std::is_same<T, atVec3f>::value || std::is_same<T, atVec4f>::value ||
void writeBool(const char* name, const bool& val); std::is_same<T, atVec2d>::value || std::is_same<T, atVec3d>::value ||
void writeByte(const char* name, const atInt8& val); std::is_same<T, atVec4d>::value>* = 0) {
void writeUByte(const char* name, const atUint8& val); if (auto v = enterSubVector(name))
void writeInt16(const char* name, const atInt16& val); for (T item : vector)
void writeUint16(const char* name, const atUint16& val); writeVal<T>(nullptr, item);
void writeInt32(const char* name, const atInt32& val); }
void writeUint32(const char* name, const atUint32& val);
void writeInt64(const char* name, const atInt64& val);
void writeUint64(const char* name, const atUint64& val);
void writeFloat(const char* name, const float& val);
void writeDouble(const char* name, const double& val);
void writeVec2f(const char* name, const atVec2f& val);
void writeVec3f(const char* name, const atVec3f& val);
void writeVec4f(const char* name, const atVec4f& val);
void writeVec2d(const char* name, const atVec2d& val);
void writeVec3d(const char* name, const atVec3d& val);
void writeVec4d(const char* name, const atVec4d& val);
void writeUBytes(const char* name, const std::unique_ptr<atUint8[]>& val, size_t byteCount);
void writeString(const char* name, std::string_view val);
void writeWString(const char* name, std::wstring_view val);
void writeU16String(const char* name, std::u16string_view val);
void writeU32String(const char* name, std::u32string_view val);
void setStyle(YAMLNodeStyle s); template <class T>
void enumerate(const char* name, const std::vector<T>& vector, std::function<void(YAMLDocWriter&, const T&)> writef) {
if (auto v = enterSubVector(name))
for (const T& item : vector)
if (auto rec = enterSubRecord(nullptr))
writef(*this, item);
}
template <typename INTYPE>
void writeVal(const char* name, const INTYPE& val);
template <typename INTYPE>
void writeVal(const char* name, const INTYPE& val, size_t byteCount);
void writeBool(const char* name, const bool& val);
void writeByte(const char* name, const atInt8& val);
void writeUByte(const char* name, const atUint8& val);
void writeInt16(const char* name, const atInt16& val);
void writeUint16(const char* name, const atUint16& val);
void writeInt32(const char* name, const atInt32& val);
void writeUint32(const char* name, const atUint32& val);
void writeInt64(const char* name, const atInt64& val);
void writeUint64(const char* name, const atUint64& val);
void writeFloat(const char* name, const float& val);
void writeDouble(const char* name, const double& val);
void writeVec2f(const char* name, const atVec2f& val);
void writeVec3f(const char* name, const atVec3f& val);
void writeVec4f(const char* name, const atVec4f& val);
void writeVec2d(const char* name, const atVec2d& val);
void writeVec3d(const char* name, const atVec3d& val);
void writeVec4d(const char* name, const atVec4d& val);
void writeUBytes(const char* name, const std::unique_ptr<atUint8[]>& val, size_t byteCount);
void writeString(const char* name, std::string_view val);
void writeWString(const char* name, std::wstring_view val);
void writeU16String(const char* name, std::u16string_view val);
void writeU32String(const char* name, std::u32string_view val);
void setStyle(YAMLNodeStyle s);
}; };
} } // namespace athena::io

View File

@ -2,151 +2,148 @@
#ifndef ZQUEST_HPP #ifndef ZQUEST_HPP
#define ZQUEST_HPP #define ZQUEST_HPP
#include "athena/Global.hpp" #include "athena/Global.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
#include <memory> #include <memory>
#define ZQUEST_VERSION_CHECK(major, minor, revision) \ #define ZQUEST_VERSION_CHECK(major, minor, revision) (major | (minor << 8) | (revision << 16))
(major | (minor << 8) | (revision << 16))
namespace athena namespace athena {
{
/*! /*!
* \brief ZQuestFile is an export format for save data. * \brief ZQuestFile is an export format for save data.
*/ */
class ZQuestFile class ZQuestFile {
{
public: public:
/*! /*!
* \brief The current major version of the ZQuest format * \brief The current major version of the ZQuest format
*/ */
static const atUint32 Major; static const atUint32 Major;
/*! /*!
* \brief The current minor version of the ZQuest format * \brief The current minor version of the ZQuest format
*/ */
static const atUint32 Minor; static const atUint32 Minor;
/*! /*!
* \brief The current revision of the ZQuest format * \brief The current revision of the ZQuest format
*/ */
static const atUint32 Revision; static const atUint32 Revision;
/*! /*!
* \brief The current version of the ZQuest format * \brief The current version of the ZQuest format
*/ */
static const atUint32 Version; static const atUint32 Version;
/*! /*!
* \brief The magic number used to identify the file e.g. "ZQS1" * \brief The magic number used to identify the file e.g. "ZQS1"
*/ */
static const atUint32 Magic; static const atUint32 Magic;
/*! /*!
* \enum Game * \enum Game
* \brief The list of games currently supported by ZQuest * \brief The list of games currently supported by ZQuest
*/ */
enum Game enum Game {
{ NoGame, //!< None or Unsupported
NoGame, //!< None or Unsupported LoZ, //!< Legend of Zelda
LoZ, //!< Legend of Zelda AoL, //!< Adventure of Link
AoL, //!< Adventure of Link ALttP, //!< A Link to the Past
ALttP, //!< A Link to the Past LA, //!< Links Awakening
LA, //!< Links Awakening OoT, //!< Ocarin of Time
OoT, //!< Ocarin of Time OoT3D, //!< Ocarina of Time 3D
OoT3D, //!< Ocarina of Time 3D MM, //!< Majora's Mask
MM, //!< Majora's Mask OoS, //!< Oracle of Season
OoS, //!< Oracle of Season OoA, //!< Oracle of Ages
OoA, //!< Oracle of Ages FS, //!< Four Swords
FS, //!< Four Swords WW, //!< Wind Waker
WW, //!< Wind Waker FSA, //!< Four Swords Adventures
FSA, //!< Four Swords Adventures MC, //!< Minish Cap
MC, //!< Minish Cap TP, //!< Twilight Princess
TP, //!< Twilight Princess PH, //!< Phantom Hourglass
PH, //!< Phantom Hourglass ST, //!< Spirit Tracks
ST, //!< Spirit Tracks SS, //!< Skyward Sword
SS, //!< Skyward Sword ALBW, //!< A Link Between Worlds
ALBW, //!< A Link Between Worlds // Add more games here
// Add more games here
// This must always be last // This must always be last
GameCount //!< Total number of supported games GameCount //!< Total number of supported games
}; };
/*! /*!
* \brief ZQuest * \brief ZQuest
*/ */
ZQuestFile(); ZQuestFile();
/*! /*!
* \brief ZQuest * \brief ZQuest
* \param game * \param game
* \param endian * \param endian
* \param data * \param data
* \param length * \param length
*/ */
ZQuestFile(Game game, Endian endian, std::unique_ptr<atUint8[]>&& data, atUint32 length, const std::string& gameString = std::string()); ZQuestFile(Game game, Endian endian, std::unique_ptr<atUint8[]>&& data, atUint32 length,
const std::string& gameString = std::string());
/*! /*!
* \brief setGame * \brief setGame
* \param game * \param game
*/ */
void setGame(Game game); void setGame(Game game);
/*! /*!
* \brief game * \brief game
* \return * \return
*/ */
Game game() const; Game game() const;
/*! /*!
* \brief setEndian * \brief setEndian
* \param endian * \param endian
*/ */
void setEndian(Endian endian); void setEndian(Endian endian);
/*! /*!
* \brief endian * \brief endian
* \return * \return
*/ */
Endian endian() const; Endian endian() const;
/*! /*!
* \brief setData * \brief setData
* \param data The data to assign * \param data The data to assign
* \param length The length of the data * \param length The length of the data
*/ */
void setData(std::unique_ptr<atUint8[]>&& data, atUint32 length); void setData(std::unique_ptr<atUint8[]>&& data, atUint32 length);
/*! /*!
* \brief data * \brief data
* \return * \return
*/ */
atUint8* data() const; atUint8* data() const;
/*! /*!
* \brief length * \brief length
* \return * \return
*/ */
atUint32 length() const; atUint32 length() const;
void setGameString(const std::string& gameString); void setGameString(const std::string& gameString);
/*! /*!
* \brief gameString * \brief gameString
* \return * \return
*/ */
std::string gameString() const; std::string gameString() const;
static const std::vector<std::string> gameStringList();
static const std::vector<std::string> gameStringList();
protected: protected:
Game m_game; Game m_game;
std::string m_gameString; std::string m_gameString;
Endian m_endian; Endian m_endian;
std::unique_ptr<atUint8[]> m_data; std::unique_ptr<atUint8[]> m_data;
atUint32 m_length; atUint32 m_length;
// Game strings support // Game strings support
}; };
} // zelda } // namespace athena
#endif // ZQUEST_HPP #endif // ZQUEST_HPP
#endif // ATHENA_NO_ZQUEST #endif // ATHENA_NO_ZQUEST

View File

@ -4,42 +4,39 @@
#include "athena/MemoryReader.hpp" #include "athena/MemoryReader.hpp"
namespace athena namespace athena {
{
class ZQuestFile; class ZQuestFile;
namespace io namespace io {
{
/*! /*!
* \brief The ZQuestFileReader class * \brief The ZQuestFileReader class
*/ */
class ZQuestFileReader : protected MemoryCopyReader class ZQuestFileReader : protected MemoryCopyReader {
{
public: public:
/*! /*!
* \brief ZQuestFileReader * \brief ZQuestFileReader
* \param data * \param data
* \param length * \param length
*/ */
ZQuestFileReader(atUint8* data, atUint64 length); ZQuestFileReader(atUint8* data, atUint64 length);
/*! /*!
* \brief ZQuestFileReader * \brief ZQuestFileReader
* \param filename * \param filename
*/ */
ZQuestFileReader(const std::string& filename); ZQuestFileReader(const std::string& filename);
/*! /*!
* \brief read * \brief read
* \return * \return
*/ */
ZQuestFile* read(); ZQuestFile* read();
}; };
} // io } // namespace io
} // zelda } // namespace athena
#endif // __ZQUESTFILEREADER_HPP__ #endif // __ZQUESTFILEREADER_HPP__

View File

@ -4,42 +4,39 @@
#include "athena/MemoryWriter.hpp" #include "athena/MemoryWriter.hpp"
namespace athena namespace athena {
{
class ZQuestFile; class ZQuestFile;
namespace io namespace io {
{
/*! /*!
* \brief The ZQuestFileWriter class * \brief The ZQuestFileWriter class
*/ */
class ZQuestFileWriter : protected MemoryCopyWriter class ZQuestFileWriter : protected MemoryCopyWriter {
{
public: public:
/*! /*!
* \brief ZQuestFileWriter * \brief ZQuestFileWriter
* \param data * \param data
* \param length * \param length
*/ */
ZQuestFileWriter(atUint8* data, atUint64 length); ZQuestFileWriter(atUint8* data, atUint64 length);
/*! /*!
* \brief ZQuestFileWriter * \brief ZQuestFileWriter
* \param filename * \param filename
*/ */
ZQuestFileWriter(const std::string& filename); ZQuestFileWriter(const std::string& filename);
/*! /*!
* \brief write * \brief write
* \param quest * \param quest
* \param compress * \param compress
*/ */
void write(ZQuestFile* quest, bool compress = true); void write(ZQuestFile* quest, bool compress = true);
}; };
} // io } // namespace io
} // zelda } // namespace athena
#endif // __ZQUESTFILEWRITER_HPP__ #endif // __ZQUESTFILEWRITER_HPP__
#endif // ATHENA_NO_ZQUEST #endif // ATHENA_NO_ZQUEST

View File

@ -688,21 +688,16 @@ class __simd_storage<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> {
public: public:
_Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; }; _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; };
void __set(size_t __index, _Tp __val) noexcept { void __set(size_t __index, _Tp __val) noexcept { (&__storage_)[__index] = __val; }
(&__storage_)[__index] = __val;
}
}; };
#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION #ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION
constexpr size_t __floor_pow_of_2(size_t __val) { constexpr size_t __floor_pow_of_2(size_t __val) {
return ((__val - 1) & __val) == 0 ? __val return ((__val - 1) & __val) == 0 ? __val : __floor_pow_of_2((__val - 1) & __val);
: __floor_pow_of_2((__val - 1) & __val);
} }
constexpr size_t __ceil_pow_of_2(size_t __val) { constexpr size_t __ceil_pow_of_2(size_t __val) { return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1; }
return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1;
}
template <class _Tp, size_t __bytes> template <class _Tp, size_t __bytes>
struct __vec_ext_traits { struct __vec_ext_traits {
@ -712,45 +707,44 @@ struct __vec_ext_traits {
}; };
#if defined(_LIBCPP_COMPILER_CLANG) #if defined(_LIBCPP_COMPILER_CLANG)
#define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \ #define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \
template <> \ template <> \
struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \ struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \
using type = \ using type = _TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT))); \
_TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT))); \
} }
#define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE) \ #define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE) \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31); \
_LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 32); _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 32);
_LIBCPP_SPECIALIZE_VEC_EXT_32(char); _LIBCPP_SPECIALIZE_VEC_EXT_32(char);
@ -777,8 +771,7 @@ _LIBCPP_SPECIALIZE_VEC_EXT_32(long double);
template <class _Tp, int __num_element> template <class _Tp, int __num_element>
class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> { class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> {
using _StorageType = using _StorageType = typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type;
typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type;
_StorageType __storage_; _StorageType __storage_;
@ -790,9 +783,7 @@ class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> {
public: public:
_Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; _Tp __get(size_t __index) const noexcept { return __storage_[__index]; };
void __set(size_t __index, _Tp __val) noexcept { void __set(size_t __index, _Tp __val) noexcept { __storage_[__index] = __val; }
__storage_[__index] = __val;
}
}; };
#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION #endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION
@ -810,8 +801,7 @@ class __simd_reference {
__simd_storage<_Tp, _Abi>* __ptr_; __simd_storage<_Tp, _Abi>* __ptr_;
size_t __index_; size_t __index_;
__simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) : __ptr_(__ptr), __index_(__index) {}
: __ptr_(__ptr), __index_(__index) {}
__simd_reference(const __simd_reference&) = default; __simd_reference(const __simd_reference&) = default;
@ -826,9 +816,7 @@ public:
return *this; return *this;
} }
__simd_reference operator++() && { __simd_reference operator++() && { return std::move(*this) = __ptr_->__get(__index_) + 1; }
return std::move(*this) = __ptr_->__get(__index_) + 1;
}
_Vp operator++(int) && { _Vp operator++(int) && {
auto __val = __ptr_->__get(__index_); auto __val = __ptr_->__get(__index_);
@ -836,9 +824,7 @@ public:
return __val; return __val;
} }
__simd_reference operator--() && { __simd_reference operator--() && { return std::move(*this) = __ptr_->__get(__index_) - 1; }
return std::move(*this) = __ptr_->__get(__index_) - 1;
}
_Vp operator--(int) && { _Vp operator--(int) && {
auto __val = __ptr_->__get(__index_); auto __val = __ptr_->__get(__index_);
@ -846,69 +832,37 @@ public:
return __val; return __val;
} }
__simd_reference operator+=(_Vp __value) && { __simd_reference operator+=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) + __value; }
return std::move(*this) = __ptr_->__get(__index_) + __value;
}
__simd_reference operator-=(_Vp __value) && { __simd_reference operator-=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) - __value; }
return std::move(*this) = __ptr_->__get(__index_) - __value;
}
__simd_reference operator*=(_Vp __value) && { __simd_reference operator*=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) * __value; }
return std::move(*this) = __ptr_->__get(__index_) * __value;
}
__simd_reference operator/=(_Vp __value) && { __simd_reference operator/=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) / __value; }
return std::move(*this) = __ptr_->__get(__index_) / __value;
}
__simd_reference operator%=(_Vp __value) && { __simd_reference operator%=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) % __value; }
return std::move(*this) = __ptr_->__get(__index_) % __value;
}
__simd_reference operator>>=(_Vp __value) && { __simd_reference operator>>=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) >> __value; }
return std::move(*this) = __ptr_->__get(__index_) >> __value;
}
__simd_reference operator<<=(_Vp __value) && { __simd_reference operator<<=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) << __value; }
return std::move(*this) = __ptr_->__get(__index_) << __value;
}
__simd_reference operator&=(_Vp __value) && { __simd_reference operator&=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) & __value; }
return std::move(*this) = __ptr_->__get(__index_) & __value;
}
__simd_reference operator|=(_Vp __value) && { __simd_reference operator|=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) | __value; }
return std::move(*this) = __ptr_->__get(__index_) | __value;
}
__simd_reference operator^=(_Vp __value) && { __simd_reference operator^=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) ^ __value; }
return std::move(*this) = __ptr_->__get(__index_) ^ __value;
}
bool operator<(_Vp __value) const { bool operator<(_Vp __value) const { return __ptr_->__get(__index_) < __value; }
return __ptr_->__get(__index_) < __value;
}
bool operator<=(_Vp __value) const { bool operator<=(_Vp __value) const { return __ptr_->__get(__index_) <= __value; }
return __ptr_->__get(__index_) <= __value;
}
bool operator>(_Vp __value) const { bool operator>(_Vp __value) const { return __ptr_->__get(__index_) > __value; }
return __ptr_->__get(__index_) > __value;
}
bool operator>=(_Vp __value) const { bool operator>=(_Vp __value) const { return __ptr_->__get(__index_) >= __value; }
return __ptr_->__get(__index_) >= __value;
}
bool operator==(_Vp __value) const { bool operator==(_Vp __value) const { return __ptr_->__get(__index_) == __value; }
return __ptr_->__get(__index_) == __value;
}
bool operator!=(_Vp __value) const { bool operator!=(_Vp __value) const { return __ptr_->__get(__index_) != __value; }
return __ptr_->__get(__index_) != __value;
}
}; };
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
@ -922,8 +876,7 @@ class __simd_mask_reference {
__simd_mask_storage<_Tp, _Abi>* __ptr_; __simd_mask_storage<_Tp, _Abi>* __ptr_;
size_t __index_; size_t __index_;
__simd_mask_reference(__simd_mask_storage<_Tp, _Abi>* __ptr, size_t __index) __simd_mask_reference(__simd_mask_storage<_Tp, _Abi>* __ptr, size_t __index) : __ptr_(__ptr), __index_(__index) {}
: __ptr_(__ptr), __index_(__index) {}
__simd_mask_reference(const __simd_mask_reference&) = default; __simd_mask_reference(const __simd_mask_reference&) = default;
@ -940,8 +893,7 @@ public:
}; };
template <class _To, class _From> template <class _To, class _From>
constexpr decltype(_To{std::declval<_From>()}, true) constexpr decltype(_To{std::declval<_From>()}, true) __is_non_narrowing_convertible_impl(_From) {
__is_non_narrowing_convertible_impl(_From) {
return true; return true;
} }
@ -951,17 +903,13 @@ constexpr bool __is_non_narrowing_convertible_impl(...) {
} }
template <class _From, class _To> template <class _From, class _To>
constexpr typename std::enable_if<std::is_arithmetic<_To>::value && constexpr typename std::enable_if<std::is_arithmetic<_To>::value && std::is_arithmetic<_From>::value, bool>::type
std::is_arithmetic<_From>::value,
bool>::type
__is_non_narrowing_arithmetic_convertible() { __is_non_narrowing_arithmetic_convertible() {
return __is_non_narrowing_convertible_impl<_To>(_From{}); return __is_non_narrowing_convertible_impl<_To>(_From{});
} }
template <class _From, class _To> template <class _From, class _To>
constexpr typename std::enable_if<!(std::is_arithmetic<_To>::value && constexpr typename std::enable_if<!(std::is_arithmetic<_To>::value && std::is_arithmetic<_From>::value), bool>::type
std::is_arithmetic<_From>::value),
bool>::type
__is_non_narrowing_arithmetic_convertible() { __is_non_narrowing_arithmetic_convertible() {
return false; return false;
} }
@ -983,11 +931,11 @@ struct __nodeduce {
template <class _Tp> template <class _Tp>
constexpr bool __vectorizable() { constexpr bool __vectorizable() {
return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value && return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value && !std::is_volatile<_Tp>::value &&
!std::is_volatile<_Tp>::value && !std::is_same<_Tp, bool>::value; !std::is_same<_Tp, bool>::value;
} }
} } // namespace athena::_simd
namespace athena::_simd::simd_abi { namespace athena::_simd::simd_abi {
using scalar = __simd_abi<_StorageKind::_Scalar, 1>; using scalar = __simd_abi<_StorageKind::_Scalar, 1>;
@ -1006,11 +954,10 @@ template <class _Tp>
using native = __simd_abi<_StorageKind::_VecExt, 16 / sizeof(_Tp)>; using native = __simd_abi<_StorageKind::_VecExt, 16 / sizeof(_Tp)>;
#else #else
template <class _Tp> template <class _Tp>
using native = using native = fixed_size<_Tp, 16 / sizeof(_Tp)>;
fixed_size<_Tp, 16 / sizeof(_Tp)>;
#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION #endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION
} } // namespace athena::_simd::simd_abi
namespace athena::_simd { namespace athena::_simd {
template <class _Tp, class _Abi = simd_abi::compatible<_Tp>> template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
@ -1032,8 +979,7 @@ template <class _Tp>
struct is_abi_tag : std::integral_constant<bool, false> {}; struct is_abi_tag : std::integral_constant<bool, false> {};
template <_StorageKind __kind, int _Np> template <_StorageKind __kind, int _Np>
struct is_abi_tag<__simd_abi<__kind, _Np>> struct is_abi_tag<__simd_abi<__kind, _Np>> : std::integral_constant<bool, true> {};
: std::integral_constant<bool, true> {};
template <class _Tp> template <class _Tp>
struct is_simd : std::integral_constant<bool, false> {}; struct is_simd : std::integral_constant<bool, false> {};
@ -1045,23 +991,19 @@ template <class _Tp>
struct is_simd_mask : std::integral_constant<bool, false> {}; struct is_simd_mask : std::integral_constant<bool, false> {};
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
struct is_simd_mask<simd_mask<_Tp, _Abi>> : std::integral_constant<bool, true> { struct is_simd_mask<simd_mask<_Tp, _Abi>> : std::integral_constant<bool, true> {};
};
template <class _Tp> template <class _Tp>
struct is_simd_flag_type : std::integral_constant<bool, false> {}; struct is_simd_flag_type : std::integral_constant<bool, false> {};
template <> template <>
struct is_simd_flag_type<element_aligned_tag> struct is_simd_flag_type<element_aligned_tag> : std::integral_constant<bool, true> {};
: std::integral_constant<bool, true> {};
template <> template <>
struct is_simd_flag_type<vector_aligned_tag> struct is_simd_flag_type<vector_aligned_tag> : std::integral_constant<bool, true> {};
: std::integral_constant<bool, true> {};
template <size_t _Align> template <size_t _Align>
struct is_simd_flag_type<overaligned_tag<_Align>> struct is_simd_flag_type<overaligned_tag<_Align>> : std::integral_constant<bool, true> {};
: std::integral_constant<bool, true> {};
template <class _Tp> template <class _Tp>
inline constexpr bool is_abi_tag_v = is_abi_tag<_Tp>::value; inline constexpr bool is_abi_tag_v = is_abi_tag<_Tp>::value;
@ -1070,8 +1012,7 @@ inline constexpr bool is_simd_v = is_simd<_Tp>::value;
template <class _Tp> template <class _Tp>
inline constexpr bool is_simd_mask_v = is_simd_mask<_Tp>::value; inline constexpr bool is_simd_mask_v = is_simd_mask<_Tp>::value;
template <class _Tp> template <class _Tp>
inline constexpr bool is_simd_flag_type_v = inline constexpr bool is_simd_flag_type_v = is_simd_flag_type<_Tp>::value;
is_simd_flag_type<_Tp>::value;
template <class _Tp, size_t _Np> template <class _Tp, size_t _Np>
struct abi_for_size { struct abi_for_size {
using type = simd_abi::fixed_size<_Np>; using type = simd_abi::fixed_size<_Np>;
@ -1083,12 +1024,9 @@ template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
struct simd_size; struct simd_size;
template <class _Tp, _StorageKind __kind, int _Np> template <class _Tp, _StorageKind __kind, int _Np>
struct simd_size<_Tp, __simd_abi<__kind, _Np>> struct simd_size<_Tp, __simd_abi<__kind, _Np>> : std::integral_constant<size_t, _Np> {
: std::integral_constant<size_t, _Np> { static_assert(std::is_arithmetic<_Tp>::value && !std::is_same<typename std::remove_const<_Tp>::type, bool>::value,
static_assert( "Element type should be vectorizable");
std::is_arithmetic<_Tp>::value &&
!std::is_same<typename std::remove_const<_Tp>::type, bool>::value,
"Element type should be vectorizable");
}; };
// TODO: implement it. // TODO: implement it.
@ -1099,8 +1037,7 @@ template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
inline constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value; inline constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value;
template <class _Tp, class _Up = typename _Tp::value_type> template <class _Tp, class _Up = typename _Tp::value_type>
inline constexpr size_t memory_alignment_v = inline constexpr size_t memory_alignment_v = memory_alignment<_Tp, _Up>::value;
memory_alignment<_Tp, _Up>::value;
// class template simd [simd.class] // class template simd [simd.class]
template <class _Tp> template <class _Tp>
@ -1125,50 +1062,41 @@ struct __static_simd_cast_traits {
template <class _Tp, class _NewAbi> template <class _Tp, class _NewAbi>
struct __static_simd_cast_traits<simd<_Tp, _NewAbi>> { struct __static_simd_cast_traits<simd<_Tp, _NewAbi>> {
template <class _Up, class _Abi> template <class _Up, class _Abi>
static typename std::enable_if<simd<_Up, _Abi>::size() == static typename std::enable_if<simd<_Up, _Abi>::size() == simd<_Tp, _NewAbi>::size(), simd<_Tp, _NewAbi>>::type
simd<_Tp, _NewAbi>::size(),
simd<_Tp, _NewAbi>>::type
__apply(const simd<_Up, _Abi>& __v); __apply(const simd<_Up, _Abi>& __v);
}; };
template <class _Tp> template <class _Tp>
struct __simd_cast_traits { struct __simd_cast_traits {
template <class _Up, class _Abi> template <class _Up, class _Abi>
static typename std::enable_if< static typename std::enable_if<__is_non_narrowing_arithmetic_convertible<_Up, _Tp>(), simd<_Tp, _Abi>>::type
__is_non_narrowing_arithmetic_convertible<_Up, _Tp>(),
simd<_Tp, _Abi>>::type
__apply(const simd<_Up, _Abi>& __v); __apply(const simd<_Up, _Abi>& __v);
}; };
template <class _Tp, class _NewAbi> template <class _Tp, class _NewAbi>
struct __simd_cast_traits<simd<_Tp, _NewAbi>> { struct __simd_cast_traits<simd<_Tp, _NewAbi>> {
template <class _Up, class _Abi> template <class _Up, class _Abi>
static typename std::enable_if< static typename std::enable_if<__is_non_narrowing_arithmetic_convertible<_Up, _Tp>() &&
__is_non_narrowing_arithmetic_convertible<_Up, _Tp>() && simd<_Up, _Abi>::size() == simd<_Tp, _NewAbi>::size(),
simd<_Up, _Abi>::size() == simd<_Tp, _NewAbi>::size(), simd<_Tp, _NewAbi>>::type
simd<_Tp, _NewAbi>>::type
__apply(const simd<_Up, _Abi>& __v); __apply(const simd<_Up, _Abi>& __v);
}; };
template <class _Tp, class _Up, class _Abi> template <class _Tp, class _Up, class _Abi>
auto simd_cast(const simd<_Up, _Abi>& __v) auto simd_cast(const simd<_Up, _Abi>& __v) -> decltype(__simd_cast_traits<_Tp>::__apply(__v)) {
-> decltype(__simd_cast_traits<_Tp>::__apply(__v)) {
return __simd_cast_traits<_Tp>::__apply(__v); return __simd_cast_traits<_Tp>::__apply(__v);
} }
template <class _Tp, class _Up, class _Abi> template <class _Tp, class _Up, class _Abi>
auto static_simd_cast(const simd<_Up, _Abi>& __v) auto static_simd_cast(const simd<_Up, _Abi>& __v) -> decltype(__static_simd_cast_traits<_Tp>::__apply(__v)) {
-> decltype(__static_simd_cast_traits<_Tp>::__apply(__v)) {
return __static_simd_cast_traits<_Tp>::__apply(__v); return __static_simd_cast_traits<_Tp>::__apply(__v);
} }
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
fixed_size_simd<_Tp, simd_size<_Tp, _Abi>::value> fixed_size_simd<_Tp, simd_size<_Tp, _Abi>::value> to_fixed_size(const simd<_Tp, _Abi>&) noexcept;
to_fixed_size(const simd<_Tp, _Abi>&) noexcept;
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
fixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value> fixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value> to_fixed_size(const simd_mask<_Tp, _Abi>&) noexcept;
to_fixed_size(const simd_mask<_Tp, _Abi>&) noexcept;
template <class _Tp, size_t _Np> template <class _Tp, size_t _Np>
native_simd<_Tp> to_native(const fixed_size_simd<_Tp, _Np>&) noexcept; native_simd<_Tp> to_native(const fixed_size_simd<_Tp, _Np>&) noexcept;
@ -1186,26 +1114,21 @@ template <size_t... __sizes, class _Tp, class _Abi>
tuple<simd<_Tp, abi_for_size_t<_Tp, __sizes>>...> split(const simd<_Tp, _Abi>&); tuple<simd<_Tp, abi_for_size_t<_Tp, __sizes>>...> split(const simd<_Tp, _Abi>&);
template <size_t... __sizes, class _Tp, class _Abi> template <size_t... __sizes, class _Tp, class _Abi>
tuple<simd_mask<_Tp, abi_for_size_t<_Tp, __sizes>>...> tuple<simd_mask<_Tp, abi_for_size_t<_Tp, __sizes>>...> split(const simd_mask<_Tp, _Abi>&);
split(const simd_mask<_Tp, _Abi>&);
template <class _SimdType, class _Abi> template <class _SimdType, class _Abi>
array<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value / array<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value / _SimdType::size()>
_SimdType::size()>
split(const simd<typename _SimdType::value_type, _Abi>&); split(const simd<typename _SimdType::value_type, _Abi>&);
template <class _SimdType, class _Abi> template <class _SimdType, class _Abi>
array<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value / array<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value / _SimdType::size()>
_SimdType::size()>
split(const simd_mask<typename _SimdType::value_type, _Abi>&); split(const simd_mask<typename _SimdType::value_type, _Abi>&);
template <class _Tp, class... _Abis> template <class _Tp, class... _Abis>
simd<_Tp, abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>> simd<_Tp, abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>> concat(const simd<_Tp, _Abis>&...);
concat(const simd<_Tp, _Abis>&...);
template <class _Tp, class... _Abis> template <class _Tp, class... _Abis>
simd_mask<_Tp, simd_mask<_Tp, abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>>
abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>>
concat(const simd_mask<_Tp, _Abis>&...); concat(const simd_mask<_Tp, _Abis>&...);
// reductions [simd.mask.reductions] // reductions [simd.mask.reductions]
@ -1239,23 +1162,20 @@ class where_expression;
// masked assignment [simd.mask.where] // masked assignment [simd.mask.where]
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
where_expression<simd_mask<_Tp, _Abi>, simd<_Tp, _Abi>> where_expression<simd_mask<_Tp, _Abi>, simd<_Tp, _Abi>> where(const typename simd<_Tp, _Abi>::mask_type&,
where(const typename simd<_Tp, _Abi>::mask_type&, simd<_Tp, _Abi>&) noexcept; simd<_Tp, _Abi>&) noexcept;
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
const_where_expression<simd_mask<_Tp, _Abi>, const simd<_Tp, _Abi>> const_where_expression<simd_mask<_Tp, _Abi>, const simd<_Tp, _Abi>> where(const typename simd<_Tp, _Abi>::mask_type&,
where(const typename simd<_Tp, _Abi>::mask_type&, const simd<_Tp, _Abi>&) noexcept;
const simd<_Tp, _Abi>&) noexcept;
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
where_expression<simd_mask<_Tp, _Abi>, simd_mask<_Tp, _Abi>> where_expression<simd_mask<_Tp, _Abi>, simd_mask<_Tp, _Abi>>
where(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&, where(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&, simd_mask<_Tp, _Abi>&) noexcept;
simd_mask<_Tp, _Abi>&) noexcept;
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
const_where_expression<simd_mask<_Tp, _Abi>, const simd_mask<_Tp, _Abi>> const_where_expression<simd_mask<_Tp, _Abi>, const simd_mask<_Tp, _Abi>>
where(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&, where(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&, const simd_mask<_Tp, _Abi>&) noexcept;
const simd_mask<_Tp, _Abi>&) noexcept;
template <class _Tp> template <class _Tp>
where_expression<bool, _Tp> where(bool, _Tp&) noexcept; where_expression<bool, _Tp> where(bool, _Tp&) noexcept;
@ -1268,45 +1188,37 @@ template <class _Tp, class _Abi, class _BinaryOp = std::plus<_Tp>>
_Tp reduce(const simd<_Tp, _Abi>&, _BinaryOp = _BinaryOp()); _Tp reduce(const simd<_Tp, _Abi>&, _BinaryOp = _BinaryOp());
template <class _MaskType, class _SimdType, class _BinaryOp> template <class _MaskType, class _SimdType, class _BinaryOp>
typename _SimdType::value_type typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&,
reduce(const const_where_expression<_MaskType, _SimdType>&, typename _SimdType::value_type neutral_element, _BinaryOp binary_op);
typename _SimdType::value_type neutral_element, _BinaryOp binary_op);
template <class _MaskType, class _SimdType> template <class _MaskType, class _SimdType>
typename _SimdType::value_type typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&,
reduce(const const_where_expression<_MaskType, _SimdType>&, plus<typename _SimdType::value_type> binary_op = {});
plus<typename _SimdType::value_type> binary_op = {});
template <class _MaskType, class _SimdType> template <class _MaskType, class _SimdType>
typename _SimdType::value_type typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&,
reduce(const const_where_expression<_MaskType, _SimdType>&, multiplies<typename _SimdType::value_type> binary_op);
multiplies<typename _SimdType::value_type> binary_op);
template <class _MaskType, class _SimdType> template <class _MaskType, class _SimdType>
typename _SimdType::value_type typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&,
reduce(const const_where_expression<_MaskType, _SimdType>&, bit_and<typename _SimdType::value_type> binary_op);
bit_and<typename _SimdType::value_type> binary_op);
template <class _MaskType, class _SimdType> template <class _MaskType, class _SimdType>
typename _SimdType::value_type typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&,
reduce(const const_where_expression<_MaskType, _SimdType>&, bit_or<typename _SimdType::value_type> binary_op);
bit_or<typename _SimdType::value_type> binary_op);
template <class _MaskType, class _SimdType> template <class _MaskType, class _SimdType>
typename _SimdType::value_type typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&,
reduce(const const_where_expression<_MaskType, _SimdType>&, bit_xor<typename _SimdType::value_type> binary_op);
bit_xor<typename _SimdType::value_type> binary_op);
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
_Tp hmin(const simd<_Tp, _Abi>&); _Tp hmin(const simd<_Tp, _Abi>&);
template <class _MaskType, class _SimdType> template <class _MaskType, class _SimdType>
typename _SimdType::value_type typename _SimdType::value_type hmin(const const_where_expression<_MaskType, _SimdType>&);
hmin(const const_where_expression<_MaskType, _SimdType>&);
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
_Tp hmax(const simd<_Tp, _Abi>&); _Tp hmax(const simd<_Tp, _Abi>&);
template <class _MaskType, class _SimdType> template <class _MaskType, class _SimdType>
typename _SimdType::value_type typename _SimdType::value_type hmax(const const_where_expression<_MaskType, _SimdType>&);
hmax(const const_where_expression<_MaskType, _SimdType>&);
// algorithms [simd.alg] // algorithms [simd.alg]
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
@ -1316,12 +1228,10 @@ template <class _Tp, class _Abi>
simd<_Tp, _Abi> max(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept; simd<_Tp, _Abi> max(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept;
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
std::pair<simd<_Tp, _Abi>, simd<_Tp, _Abi>> std::pair<simd<_Tp, _Abi>, simd<_Tp, _Abi>> minmax(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept;
minmax(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept;
template <class _Tp, class _Abi> template <class _Tp, class _Abi>
simd<_Tp, _Abi> clamp(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&, simd<_Tp, _Abi> clamp(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&);
const simd<_Tp, _Abi>&);
// [simd.whereexpr] // [simd.whereexpr]
// TODO implement where expressions. // TODO implement where expressions.
@ -1387,6 +1297,7 @@ public:
auto end() { return std::end(__data_); } auto end() { return std::end(__data_); }
auto begin() const { return std::begin(__data_); } auto begin() const { return std::begin(__data_); }
auto end() const { return std::end(__data_); } auto end() const { return std::end(__data_); }
private: private:
value_type __data_[_Simd::size()]; value_type __data_[_Simd::size()];
}; };
@ -1396,6 +1307,7 @@ template <class _Tp, class _Abi>
class simd { class simd {
template <class _Up, class _UAbi> template <class _Up, class _UAbi>
friend class simd; friend class simd;
public: public:
using value_type = _Tp; using value_type = _Tp;
using reference = __simd_reference<_Tp, _Tp, _Abi>; using reference = __simd_reference<_Tp, _Tp, _Abi>;
@ -1406,34 +1318,25 @@ public:
simd(const simd&) = default; simd(const simd&) = default;
simd& operator=(const simd&) = default; simd& operator=(const simd&) = default;
static constexpr size_t size() noexcept { static constexpr size_t size() noexcept { return simd_size<_Tp, _Abi>::value; }
return simd_size<_Tp, _Abi>::value;
}
private: private:
__simd_storage<_Tp, _Abi> __s_; __simd_storage<_Tp, _Abi> __s_;
template <class _Up> template <class _Up>
static constexpr bool __can_broadcast() { static constexpr bool __can_broadcast() {
return (std::is_arithmetic<_Up>::value && return (std::is_arithmetic<_Up>::value && __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()) ||
__is_non_narrowing_arithmetic_convertible<_Up, _Tp>()) || (!std::is_arithmetic<_Up>::value && std::is_convertible<_Up, _Tp>::value) ||
(!std::is_arithmetic<_Up>::value &&
std::is_convertible<_Up, _Tp>::value) ||
std::is_same<typename std::remove_const<_Up>::type, int>::value || std::is_same<typename std::remove_const<_Up>::type, int>::value ||
(std::is_same<typename std::remove_const<_Up>::type, (std::is_same<typename std::remove_const<_Up>::type, unsigned int>::value && std::is_unsigned<_Tp>::value);
unsigned int>::value &&
std::is_unsigned<_Tp>::value);
} }
template <class _Generator, size_t... __indicies> template <class _Generator, size_t... __indicies>
static constexpr decltype( static constexpr decltype(
std::forward_as_tuple(std::declval<_Generator>()( std::forward_as_tuple(std::declval<_Generator>()(std::integral_constant<size_t, __indicies>())...), bool())
std::integral_constant<size_t, __indicies>())...),
bool())
__can_generate(std::index_sequence<__indicies...>) { __can_generate(std::index_sequence<__indicies...>) {
return !__variadic_sum<bool>( return !__variadic_sum<bool>(
!__can_broadcast<decltype(std::declval<_Generator>()( !__can_broadcast<decltype(std::declval<_Generator>()(std::integral_constant<size_t, __indicies>()))>()...);
std::integral_constant<size_t, __indicies>()))>()...);
} }
template <class _Generator> template <class _Generator>
@ -1443,9 +1346,7 @@ private:
template <class _Generator, size_t... __indicies> template <class _Generator, size_t... __indicies>
void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) { void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) {
int __not_used[]{((*this)[__indicies] = int __not_used[]{((*this)[__indicies] = __g(std::integral_constant<size_t, __indicies>()), 0)...};
__g(std::integral_constant<size_t, __indicies>()),
0)...};
(void)__not_used; (void)__not_used;
} }
@ -1466,8 +1367,8 @@ public:
#endif #endif
// implicit type conversion constructor // implicit type conversion constructor
template <class _Up, class _UAbi, template <class _Up, class _UAbi,
class = typename std::enable_if<std::is_constructible< class = typename std::enable_if<
__simd_storage<_Tp, _Abi>, __simd_storage<_Up, _UAbi>>::value>> std::is_constructible<__simd_storage<_Tp, _Abi>, __simd_storage<_Up, _UAbi>>::value>>
simd(const simd<_Up, _UAbi>& __v) : __s_(__v.__s_) {} simd(const simd<_Up, _UAbi>& __v) : __s_(__v.__s_) {}
#if 0 #if 0
@ -1489,29 +1390,20 @@ public:
__s_.__broadcast(v); __s_.__broadcast(v);
} }
#endif #endif
simd(_Tp __rv) { simd(_Tp __rv) { __s_.__broadcast(__rv); }
__s_.__broadcast(__rv);
}
simd(_Tp a, _Tp b, _Tp c = {}, _Tp d = {}) { simd(_Tp a, _Tp b, _Tp c = {}, _Tp d = {}) { __s_.__set4(a, b, c, d); }
__s_.__set4(a, b, c, d);
}
// generator constructor // generator constructor
template <class _Generator, template <class _Generator,
int = typename std::enable_if< int = typename std::enable_if<__can_generate<_Generator>(std::make_index_sequence<size()>()), int>::type()>
__can_generate<_Generator>(std::make_index_sequence<size()>()),
int>::type()>
explicit simd(_Generator&& __g) { explicit simd(_Generator&& __g) {
__generator_init(std::forward<_Generator>(__g), __generator_init(std::forward<_Generator>(__g), std::make_index_sequence<size()>());
std::make_index_sequence<size()>());
} }
// load constructor // load constructor
template < template <class _Up, class _Flags, class = typename std::enable_if<__vectorizable<_Up>()>::type,
class _Up, class _Flags, class = typename std::enable_if<is_simd_flag_type<_Flags>::value>::type>
class = typename std::enable_if<__vectorizable<_Up>()>::type,
class = typename std::enable_if<is_simd_flag_type<_Flags>::value>::type>
simd(const _Up* __buffer, _Flags) { simd(const _Up* __buffer, _Flags) {
// TODO: optimize for overaligned flags // TODO: optimize for overaligned flags
for (size_t __i = 0; __i < size(); __i++) { for (size_t __i = 0; __i < size(); __i++) {
@ -1529,9 +1421,7 @@ public:
} }
#endif #endif
// loads [simd.load] // loads [simd.load]
void copy_from(const simd_data<simd>& __buffer) { void copy_from(const simd_data<simd>& __buffer) { __s_.__copy_from(__buffer); }
__s_.__copy_from(__buffer);
}
#if 0 #if 0
// stores [simd.store] // stores [simd.store]
@ -1546,9 +1436,7 @@ public:
} }
#endif #endif
// stores [simd.store] // stores [simd.store]
void copy_to(simd_data<simd>& __buffer) const { void copy_to(simd_data<simd>& __buffer) const { __s_.__copy_to(__buffer); }
__s_.__copy_to(__buffer);
}
// scalar access [simd.subscr] // scalar access [simd.subscr]
reference operator[](size_t __i) { return reference(&__s_, __i); } reference operator[](size_t __i) { return reference(&__s_, __i); }
@ -1606,7 +1494,7 @@ public:
value_type dot3(const simd& other) const { return __s_.__dot3(other.__s_); } value_type dot3(const simd& other) const { return __s_.__dot3(other.__s_); }
value_type dot4(const simd& other) const { return __s_.__dot4(other.__s_); } value_type dot4(const simd& other) const { return __s_.__dot4(other.__s_); }
template<int x, int y, int z, int w> template <int x, int y, int z, int w>
simd shuffle() const { simd shuffle() const {
simd s; simd s;
s.__s_ = __s_.template __shuffle<x, y, z, w>(); s.__s_ = __s_.template __shuffle<x, y, z, w>();
@ -1624,9 +1512,7 @@ public:
using reference = __simd_mask_reference<_Tp, _Abi>; using reference = __simd_mask_reference<_Tp, _Abi>;
using simd_type = simd<_Tp, _Abi>; using simd_type = simd<_Tp, _Abi>;
using abi_type = _Abi; using abi_type = _Abi;
static constexpr size_t size() noexcept { static constexpr size_t size() noexcept { return simd_size<_Tp, _Abi>::value; }
return simd_size<_Tp, _Abi>::value;
}
simd_mask() = default; simd_mask() = default;
// broadcast constructor // broadcast constructor
@ -1683,12 +1569,15 @@ public:
}; };
template <class _Simd> template <class _Simd>
inline simd_data<_Simd>::simd_data(const _Simd& s) { s.copy_to(*this); } inline simd_data<_Simd>::simd_data(const _Simd& s) {
s.copy_to(*this);
}
template <class _Tp, int __num_element> template <class _Tp, int __num_element>
class __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> { class __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> {
public: public:
using storage_type = std::array<_Tp, __num_element>; using storage_type = std::array<_Tp, __num_element>;
private: private:
storage_type __storage_; storage_type __storage_;
@ -1700,34 +1589,26 @@ private:
public: public:
_Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; _Tp __get(size_t __index) const noexcept { return __storage_[__index]; };
void __set(size_t __index, _Tp __val) noexcept { void __set(size_t __index, _Tp __val) noexcept { __storage_[__index] = __val; }
__storage_[__index] = __val;
}
std::enable_if_t<__num_element >= 4> __set4(float a, float b, float c, float d) noexcept { std::enable_if_t<__num_element >= 4> __set4(float a, float b, float c, float d) noexcept {
__storage_[0] = a; __storage_[0] = a;
__storage_[1] = b; __storage_[1] = b;
__storage_[2] = c; __storage_[2] = c;
__storage_[3] = d; __storage_[3] = d;
} }
void __broadcast(float __val) noexcept { void __broadcast(float __val) noexcept { std::fill(__storage_.begin(), __storage_.end(), __val); }
std::fill(__storage_.begin(), __storage_.end(), __val);
}
std::enable_if_t<__num_element >= 2, _Tp> __dot2(const __simd_storage& other) const noexcept { std::enable_if_t<__num_element >= 2, _Tp> __dot2(const __simd_storage& other) const noexcept {
return __storage_[0] * other.__storage_[0] + return __storage_[0] * other.__storage_[0] + __storage_[1] * other.__storage_[1];
__storage_[1] * other.__storage_[1];
} }
std::enable_if_t<__num_element >= 3, _Tp> __dot3(const __simd_storage& other) const noexcept { std::enable_if_t<__num_element >= 3, _Tp> __dot3(const __simd_storage& other) const noexcept {
return __storage_[0] * other.__storage_[0] + return __storage_[0] * other.__storage_[0] + __storage_[1] * other.__storage_[1] +
__storage_[1] * other.__storage_[1] +
__storage_[2] * other.__storage_[2]; __storage_[2] * other.__storage_[2];
} }
std::enable_if_t<__num_element >= 4, _Tp> __dot4(const __simd_storage& other) const noexcept { std::enable_if_t<__num_element >= 4, _Tp> __dot4(const __simd_storage& other) const noexcept {
return __storage_[0] * other.__storage_[0] + return __storage_[0] * other.__storage_[0] + __storage_[1] * other.__storage_[1] +
__storage_[1] * other.__storage_[1] + __storage_[2] * other.__storage_[2] + __storage_[3] * other.__storage_[3];
__storage_[2] * other.__storage_[2] +
__storage_[3] * other.__storage_[3];
} }
template<int x, int y, int z, int w> template <int x, int y, int z, int w>
std::enable_if_t<__num_element >= 4, __simd_storage> __shuffle() const noexcept { std::enable_if_t<__num_element >= 4, __simd_storage> __shuffle() const noexcept {
__simd_storage s; __simd_storage s;
s.__storage_[0] = __storage_[x]; s.__storage_[0] = __storage_[x];
@ -1756,13 +1637,10 @@ public:
template <class _Tp, int __num_element> template <class _Tp, int __num_element>
class __simd_mask_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> { class __simd_mask_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> {
std::bitset<__num_element> __storage_; std::bitset<__num_element> __storage_;
public: public:
bool __get(size_t __index) const noexcept { bool __get(size_t __index) const noexcept { return __storage_.test(__index); }
return __storage_.test(__index); void __set(size_t __index, bool __val) noexcept { __storage_.set(__index, __val); }
}
void __set(size_t __index, bool __val) noexcept {
__storage_.set(__index, __val);
}
}; };
} } // namespace athena::_simd

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#define _ATHENA_SIMD_INCLUDED #define _ATHENA_SIMD_INCLUDED
namespace athena::_simd { using namespace std; } namespace athena::_simd {
using namespace std;
}
#include "parallelism_v2_simd.hpp" #include "parallelism_v2_simd.hpp"
#if _M_IX86_FP >= 1 || _M_X64 #if _M_IX86_FP >= 1 || _M_X64
#define __SSE__ 1 #define __SSE__ 1
@ -11,16 +13,23 @@ namespace athena::_simd { using namespace std; }
#include "simd_sse.hpp" #include "simd_sse.hpp"
#else #else
namespace simd_abi { namespace simd_abi {
template<typename T> struct athena_native {}; template <typename T>
template<> struct athena_native<float> { using type = fixed_size<4>; }; struct athena_native {};
template<> struct athena_native<double> { using type = fixed_size<4>; }; template <>
} struct athena_native<float> {
using type = fixed_size<4>;
};
template <>
struct athena_native<double> {
using type = fixed_size<4>;
};
} // namespace simd_abi
#endif #endif
namespace athena { namespace athena {
template<typename T> using simd = _simd::simd<T, template <typename T>
typename _simd::simd_abi::athena_native<T>::type>; using simd = _simd::simd<T, typename _simd::simd_abi::athena_native<T>::type>;
template<typename T> template <typename T>
using simd_values = _simd::simd_data<simd<T>>; using simd_values = _simd::simd_data<simd<T>>;
using simd_floats = simd_values<float>; using simd_floats = simd_values<float>;
using simd_doubles = simd_values<double>; using simd_doubles = simd_values<double>;
} } // namespace athena

View File

@ -6,7 +6,7 @@
#include <immintrin.h> #include <immintrin.h>
namespace athena::_simd { namespace athena::_simd {
// __m256d storage for AVX // __m256d storage for AVX
template<> template <>
class __simd_storage<double, m256d_abi> { class __simd_storage<double, m256d_abi> {
public: public:
using storage_type = __m256d; using storage_type = __m256d;
@ -22,12 +22,8 @@ public:
sse_data[__index] = __val; sse_data[__index] = __val;
__storage_ = _mm256_load_pd(sse_data.data()); __storage_ = _mm256_load_pd(sse_data.data());
} }
void __set4(double a, double b, double c, double d) noexcept { void __set4(double a, double b, double c, double d) noexcept { __storage_ = _mm256_set_pd(d, c, b, a); }
__storage_ = _mm256_set_pd(d, c, b, a); void __broadcast(double __val) noexcept { __storage_ = _mm256_set1_pd(__val); }
}
void __broadcast(double __val) noexcept {
__storage_ = _mm256_set1_pd(__val);
}
double __dot2(const __simd_storage<double, m256d_abi>& other) const noexcept { double __dot2(const __simd_storage<double, m256d_abi>& other) const noexcept {
alignas(32) std::array<double, 4> sse_data; alignas(32) std::array<double, 4> sse_data;
_mm256_store_pd(sse_data.data(), _mm256_mul_pd(__storage_, other.__storage_)); _mm256_store_pd(sse_data.data(), _mm256_mul_pd(__storage_, other.__storage_));
@ -61,7 +57,7 @@ public:
const storage_type& __native() const { return __storage_; } const storage_type& __native() const { return __storage_; }
}; };
// __m256d mask storage for AVX // __m256d mask storage for AVX
template<> template <>
class __simd_mask_storage<double, m256d_abi> : public __simd_storage<double, m256d_abi> { class __simd_mask_storage<double, m256d_abi> : public __simd_storage<double, m256d_abi> {
public: public:
bool __get(size_t __index) const noexcept { bool __get(size_t __index) const noexcept {
@ -83,95 +79,87 @@ inline simd<double, m256d_abi> simd<double, m256d_abi>::operator-() const {
return _mm256_xor_pd(__s_.__storage_, _mm256_set1_pd(-0.0)); return _mm256_xor_pd(__s_.__storage_, _mm256_set1_pd(-0.0));
} }
inline simd<double, m256d_abi> inline simd<double, m256d_abi> operator+(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
operator+(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
simd<double, m256d_abi> ret; simd<double, m256d_abi> ret;
ret.__s_.__storage_ = _mm256_add_pd(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm256_add_pd(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<double, m256d_abi> inline simd<double, m256d_abi> operator-(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
operator-(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
simd<double, m256d_abi> ret; simd<double, m256d_abi> ret;
ret.__s_.__storage_ = _mm256_sub_pd(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm256_sub_pd(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<double, m256d_abi> inline simd<double, m256d_abi> operator*(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
operator*(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
simd<double, m256d_abi> ret; simd<double, m256d_abi> ret;
ret.__s_.__storage_ = _mm256_mul_pd(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm256_mul_pd(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<double, m256d_abi> inline simd<double, m256d_abi> operator/(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
operator/(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
simd<double, m256d_abi> ret; simd<double, m256d_abi> ret;
ret.__s_.__storage_ = _mm256_div_pd(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm256_div_pd(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<double, m256d_abi>& inline simd<double, m256d_abi>& operator+=(simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
operator+=(simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
a.__s_.__storage_ = _mm256_add_pd(a.__s_.__storage_, b.__s_.__storage_); a.__s_.__storage_ = _mm256_add_pd(a.__s_.__storage_, b.__s_.__storage_);
return a; return a;
} }
inline simd<double, m256d_abi>& inline simd<double, m256d_abi>& operator-=(simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
operator-=(simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
a.__s_.__storage_ = _mm256_sub_pd(a.__s_.__storage_, b.__s_.__storage_); a.__s_.__storage_ = _mm256_sub_pd(a.__s_.__storage_, b.__s_.__storage_);
return a; return a;
} }
inline simd<double, m256d_abi>& inline simd<double, m256d_abi>& operator*=(simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
operator*=(simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
a.__s_.__storage_ = _mm256_mul_pd(a.__s_.__storage_, b.__s_.__storage_); a.__s_.__storage_ = _mm256_mul_pd(a.__s_.__storage_, b.__s_.__storage_);
return a; return a;
} }
inline simd<double, m256d_abi>& inline simd<double, m256d_abi>& operator/=(simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
operator/=(simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) {
a.__s_.__storage_ = _mm256_div_pd(a.__s_.__storage_, b.__s_.__storage_); a.__s_.__storage_ = _mm256_div_pd(a.__s_.__storage_, b.__s_.__storage_);
return a; return a;
} }
inline simd<double, m256d_abi>::mask_type inline simd<double, m256d_abi>::mask_type operator==(const simd<double, m256d_abi>& a,
operator==(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) { const simd<double, m256d_abi>& b) {
simd<double, m256d_abi>::mask_type ret; simd<double, m256d_abi>::mask_type ret;
ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_EQ_OQ); ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_EQ_OQ);
return ret; return ret;
} }
inline simd<double, m256d_abi>::mask_type inline simd<double, m256d_abi>::mask_type operator!=(const simd<double, m256d_abi>& a,
operator!=(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) { const simd<double, m256d_abi>& b) {
simd<double, m256d_abi>::mask_type ret; simd<double, m256d_abi>::mask_type ret;
ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_NEQ_OQ); ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_NEQ_OQ);
return ret; return ret;
} }
inline simd<double, m256d_abi>::mask_type inline simd<double, m256d_abi>::mask_type operator>=(const simd<double, m256d_abi>& a,
operator>=(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) { const simd<double, m256d_abi>& b) {
simd<double, m256d_abi>::mask_type ret; simd<double, m256d_abi>::mask_type ret;
ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_GE_OQ); ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_GE_OQ);
return ret; return ret;
} }
inline simd<double, m256d_abi>::mask_type inline simd<double, m256d_abi>::mask_type operator<=(const simd<double, m256d_abi>& a,
operator<=(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) { const simd<double, m256d_abi>& b) {
simd<double, m256d_abi>::mask_type ret; simd<double, m256d_abi>::mask_type ret;
ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_LE_OQ); ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_LE_OQ);
return ret; return ret;
} }
inline simd<double, m256d_abi>::mask_type inline simd<double, m256d_abi>::mask_type operator>(const simd<double, m256d_abi>& a,
operator>(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) { const simd<double, m256d_abi>& b) {
simd<double, m256d_abi>::mask_type ret; simd<double, m256d_abi>::mask_type ret;
ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_GT_OQ); ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_GT_OQ);
return ret; return ret;
} }
inline simd<double, m256d_abi>::mask_type inline simd<double, m256d_abi>::mask_type operator<(const simd<double, m256d_abi>& a,
operator<(const simd<double, m256d_abi>& a, const simd<double, m256d_abi>& b) { const simd<double, m256d_abi>& b) {
simd<double, m256d_abi>::mask_type ret; simd<double, m256d_abi>::mask_type ret;
ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_LT_OQ); ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_LT_OQ);
return ret; return ret;
@ -182,7 +170,10 @@ inline __simd_storage<float, m128_abi>::__simd_storage(const __simd_storage<doub
} }
namespace simd_abi { namespace simd_abi {
template<> struct athena_native<double> { using type = m256d_abi; }; template <>
struct athena_native<double> {
using type = m256d_abi;
};
} // namespace simd_abi } // namespace simd_abi
} // namespace athena::_simd } // namespace athena::_simd

View File

@ -40,12 +40,8 @@ public:
sse_data[__index] = __val; sse_data[__index] = __val;
__storage_ = _mm_load_ps(sse_data.data()); __storage_ = _mm_load_ps(sse_data.data());
} }
void __set4(float a, float b, float c, float d) noexcept { void __set4(float a, float b, float c, float d) noexcept { __storage_ = _mm_set_ps(d, c, b, a); }
__storage_ = _mm_set_ps(d, c, b, a); void __broadcast(float __val) noexcept { __storage_ = _mm_set1_ps(__val); }
}
void __broadcast(float __val) noexcept {
__storage_ = _mm_set1_ps(__val);
}
float __dot2(const __simd_storage<float, m128_abi>& other) const noexcept { float __dot2(const __simd_storage<float, m128_abi>& other) const noexcept {
#if __SSE4_1__ #if __SSE4_1__
float ret; float ret;
@ -79,7 +75,7 @@ public:
return sse_data[0] + sse_data[1] + sse_data[2] + sse_data[3]; return sse_data[0] + sse_data[1] + sse_data[2] + sse_data[3];
#endif #endif
} }
template<int x, int y, int z, int w> template <int x, int y, int z, int w>
__simd_storage __shuffle() const noexcept { __simd_storage __shuffle() const noexcept {
__simd_storage s; __simd_storage s;
s.__storage_ = _mm_shuffle_ps(__storage_, __storage_, _MM_SHUFFLE(w, z, y, x)); s.__storage_ = _mm_shuffle_ps(__storage_, __storage_, _MM_SHUFFLE(w, z, y, x));
@ -105,8 +101,7 @@ public:
}; };
// __m128 mask storage for SSE2+ // __m128 mask storage for SSE2+
template <> template <>
class __simd_mask_storage<float, m128_abi> : public __simd_storage<float, m128_abi> class __simd_mask_storage<float, m128_abi> : public __simd_storage<float, m128_abi> {
{
public: public:
bool __get(size_t __index) const noexcept { bool __get(size_t __index) const noexcept {
alignas(16) uint32_t sse_data[4]; alignas(16) uint32_t sse_data[4];
@ -126,95 +121,81 @@ inline simd<float, m128_abi> simd<float, m128_abi>::operator-() const {
return _mm_xor_ps(__s_.__storage_, _mm_set1_ps(-0.f)); return _mm_xor_ps(__s_.__storage_, _mm_set1_ps(-0.f));
} }
inline simd<float, m128_abi> inline simd<float, m128_abi> operator+(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator+(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
simd<float, m128_abi> ret; simd<float, m128_abi> ret;
ret.__s_.__storage_ = _mm_add_ps(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm_add_ps(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<float, m128_abi> inline simd<float, m128_abi> operator-(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator-(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
simd<float, m128_abi> ret; simd<float, m128_abi> ret;
ret.__s_.__storage_ = _mm_sub_ps(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm_sub_ps(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<float, m128_abi> inline simd<float, m128_abi> operator*(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator*(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
simd<float, m128_abi> ret; simd<float, m128_abi> ret;
ret.__s_.__storage_ = _mm_mul_ps(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm_mul_ps(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<float, m128_abi> inline simd<float, m128_abi> operator/(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator/(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
simd<float, m128_abi> ret; simd<float, m128_abi> ret;
ret.__s_.__storage_ = _mm_div_ps(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm_div_ps(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<float, m128_abi>& inline simd<float, m128_abi>& operator+=(simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator+=(simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
a.__s_.__storage_ = _mm_add_ps(a.__s_.__storage_, b.__s_.__storage_); a.__s_.__storage_ = _mm_add_ps(a.__s_.__storage_, b.__s_.__storage_);
return a; return a;
} }
inline simd<float, m128_abi>& inline simd<float, m128_abi>& operator-=(simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator-=(simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
a.__s_.__storage_ = _mm_sub_ps(a.__s_.__storage_, b.__s_.__storage_); a.__s_.__storage_ = _mm_sub_ps(a.__s_.__storage_, b.__s_.__storage_);
return a; return a;
} }
inline simd<float, m128_abi>& inline simd<float, m128_abi>& operator*=(simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator*=(simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
a.__s_.__storage_ = _mm_mul_ps(a.__s_.__storage_, b.__s_.__storage_); a.__s_.__storage_ = _mm_mul_ps(a.__s_.__storage_, b.__s_.__storage_);
return a; return a;
} }
inline simd<float, m128_abi>& inline simd<float, m128_abi>& operator/=(simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator/=(simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
a.__s_.__storage_ = _mm_div_ps(a.__s_.__storage_, b.__s_.__storage_); a.__s_.__storage_ = _mm_div_ps(a.__s_.__storage_, b.__s_.__storage_);
return a; return a;
} }
inline simd<float, m128_abi>::mask_type inline simd<float, m128_abi>::mask_type operator==(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator==(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
simd<float, m128_abi>::mask_type ret; simd<float, m128_abi>::mask_type ret;
ret.__s_.__storage_ = _mm_cmpeq_ps(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm_cmpeq_ps(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<float, m128_abi>::mask_type inline simd<float, m128_abi>::mask_type operator!=(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator!=(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
simd<float, m128_abi>::mask_type ret; simd<float, m128_abi>::mask_type ret;
ret.__s_.__storage_ = _mm_cmpneq_ps(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm_cmpneq_ps(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<float, m128_abi>::mask_type inline simd<float, m128_abi>::mask_type operator>=(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator>=(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
simd<float, m128_abi>::mask_type ret; simd<float, m128_abi>::mask_type ret;
ret.__s_.__storage_ = _mm_cmpge_ps(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm_cmpge_ps(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<float, m128_abi>::mask_type inline simd<float, m128_abi>::mask_type operator<=(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator<=(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
simd<float, m128_abi>::mask_type ret; simd<float, m128_abi>::mask_type ret;
ret.__s_.__storage_ = _mm_cmple_ps(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm_cmple_ps(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<float, m128_abi>::mask_type inline simd<float, m128_abi>::mask_type operator>(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator>(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
simd<float, m128_abi>::mask_type ret; simd<float, m128_abi>::mask_type ret;
ret.__s_.__storage_ = _mm_cmpgt_ps(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm_cmpgt_ps(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
} }
inline simd<float, m128_abi>::mask_type inline simd<float, m128_abi>::mask_type operator<(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
operator<(const simd<float, m128_abi>& a, const simd<float, m128_abi>& b) {
simd<float, m128_abi>::mask_type ret; simd<float, m128_abi>::mask_type ret;
ret.__s_.__storage_ = _mm_cmplt_ps(a.__s_.__storage_, b.__s_.__storage_); ret.__s_.__storage_ = _mm_cmplt_ps(a.__s_.__storage_, b.__s_.__storage_);
return ret; return ret;
@ -308,8 +289,7 @@ public:
}; };
// __m128d mask storage for SSE2+ // __m128d mask storage for SSE2+
template <> template <>
class __simd_mask_storage<double, m128d_abi> : public __simd_storage<double, m128d_abi> class __simd_mask_storage<double, m128d_abi> : public __simd_storage<double, m128d_abi> {
{
public: public:
bool __get(size_t __index) const noexcept { bool __get(size_t __index) const noexcept {
alignas(16) uint64_t sse_data[2]; alignas(16) uint64_t sse_data[2];
@ -332,108 +312,100 @@ inline simd<double, m128d_abi> simd<double, m128d_abi>::operator-() const {
return ret; return ret;
} }
inline simd<double, m128d_abi> inline simd<double, m128d_abi> operator+(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
operator+(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
simd<double, m128d_abi> ret; simd<double, m128d_abi> ret;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
ret.__s_.__storage_[i] = _mm_add_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); ret.__s_.__storage_[i] = _mm_add_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return ret; return ret;
} }
inline simd<double, m128d_abi> inline simd<double, m128d_abi> operator-(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
operator-(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
simd<double, m128d_abi> ret; simd<double, m128d_abi> ret;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
ret.__s_.__storage_[i] = _mm_sub_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); ret.__s_.__storage_[i] = _mm_sub_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return ret; return ret;
} }
inline simd<double, m128d_abi> inline simd<double, m128d_abi> operator*(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
operator*(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
simd<double, m128d_abi> ret; simd<double, m128d_abi> ret;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
ret.__s_.__storage_[i] = _mm_mul_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); ret.__s_.__storage_[i] = _mm_mul_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return ret; return ret;
} }
inline simd<double, m128d_abi> inline simd<double, m128d_abi> operator/(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
operator/(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
simd<double, m128d_abi> ret; simd<double, m128d_abi> ret;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
ret.__s_.__storage_[i] = _mm_div_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); ret.__s_.__storage_[i] = _mm_div_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return ret; return ret;
} }
inline simd<double, m128d_abi>& inline simd<double, m128d_abi>& operator+=(simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
operator+=(simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
a.__s_.__storage_[i] = _mm_add_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); a.__s_.__storage_[i] = _mm_add_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return a; return a;
} }
inline simd<double, m128d_abi>& inline simd<double, m128d_abi>& operator-=(simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
operator-=(simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
a.__s_.__storage_[i] = _mm_sub_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); a.__s_.__storage_[i] = _mm_sub_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return a; return a;
} }
inline simd<double, m128d_abi>& inline simd<double, m128d_abi>& operator*=(simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
operator*=(simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
a.__s_.__storage_[i] = _mm_mul_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); a.__s_.__storage_[i] = _mm_mul_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return a; return a;
} }
inline simd<double, m128d_abi>& inline simd<double, m128d_abi>& operator/=(simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
operator/=(simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) {
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
a.__s_.__storage_[i] = _mm_div_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); a.__s_.__storage_[i] = _mm_div_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return a; return a;
} }
inline simd<double, m128d_abi>::mask_type inline simd<double, m128d_abi>::mask_type operator==(const simd<double, m128d_abi>& a,
operator==(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) { const simd<double, m128d_abi>& b) {
simd<double, m128d_abi>::mask_type ret; simd<double, m128d_abi>::mask_type ret;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
ret.__s_.__storage_[i] = _mm_cmpeq_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); ret.__s_.__storage_[i] = _mm_cmpeq_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return ret; return ret;
} }
inline simd<double, m128d_abi>::mask_type inline simd<double, m128d_abi>::mask_type operator!=(const simd<double, m128d_abi>& a,
operator!=(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) { const simd<double, m128d_abi>& b) {
simd<double, m128d_abi>::mask_type ret; simd<double, m128d_abi>::mask_type ret;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
ret.__s_.__storage_[i] = _mm_cmpneq_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); ret.__s_.__storage_[i] = _mm_cmpneq_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return ret; return ret;
} }
inline simd<double, m128d_abi>::mask_type inline simd<double, m128d_abi>::mask_type operator>=(const simd<double, m128d_abi>& a,
operator>=(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) { const simd<double, m128d_abi>& b) {
simd<double, m128d_abi>::mask_type ret; simd<double, m128d_abi>::mask_type ret;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
ret.__s_.__storage_[i] = _mm_cmpge_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); ret.__s_.__storage_[i] = _mm_cmpge_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return ret; return ret;
} }
inline simd<double, m128d_abi>::mask_type inline simd<double, m128d_abi>::mask_type operator<=(const simd<double, m128d_abi>& a,
operator<=(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) { const simd<double, m128d_abi>& b) {
simd<double, m128d_abi>::mask_type ret; simd<double, m128d_abi>::mask_type ret;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
ret.__s_.__storage_[i] = _mm_cmple_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); ret.__s_.__storage_[i] = _mm_cmple_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return ret; return ret;
} }
inline simd<double, m128d_abi>::mask_type inline simd<double, m128d_abi>::mask_type operator>(const simd<double, m128d_abi>& a,
operator>(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) { const simd<double, m128d_abi>& b) {
simd<double, m128d_abi>::mask_type ret; simd<double, m128d_abi>::mask_type ret;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
ret.__s_.__storage_[i] = _mm_cmpgt_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); ret.__s_.__storage_[i] = _mm_cmpgt_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
return ret; return ret;
} }
inline simd<double, m128d_abi>::mask_type inline simd<double, m128d_abi>::mask_type operator<(const simd<double, m128d_abi>& a,
operator<(const simd<double, m128d_abi>& a, const simd<double, m128d_abi>& b) { const simd<double, m128d_abi>& b) {
simd<double, m128d_abi>::mask_type ret; simd<double, m128d_abi>::mask_type ret;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
ret.__s_.__storage_[i] = _mm_cmplt_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); ret.__s_.__storage_[i] = _mm_cmplt_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]);
@ -445,10 +417,17 @@ inline __simd_storage<float, m128_abi>::__simd_storage(const __simd_storage<doub
} }
namespace simd_abi { namespace simd_abi {
template<typename T> struct athena_native {}; template <typename T>
template<> struct athena_native<float> { using type = m128_abi; }; struct athena_native {};
template <>
struct athena_native<float> {
using type = m128_abi;
};
#ifndef __AVX__ #ifndef __AVX__
template<> struct athena_native<double> { using type = m128d_abi; }; template <>
struct athena_native<double> {
using type = m128d_abi;
};
#endif #endif
} // namespace simd_abi } // namespace simd_abi

View File

@ -1,13 +1,11 @@
#pragma once #pragma once
#include "athena/Types.hpp" #include "athena/Types.hpp"
namespace bignum namespace bignum {
{
int compare(const atUint8* a, const atUint8* b, atUint32 n); int compare(const atUint8* a, const atUint8* b, atUint32 n);
void subModulus(atUint8* a, const atUint8* N, atUint32 n); void subModulus(atUint8* a, const atUint8* N, atUint32 n);
void add(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n); void add(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n);
void mul(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n); void mul(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n);
void exp(atUint8* d, const atUint8* a, const atUint8* N, atUint32 n, atUint8* e, atUint32 en); void exp(atUint8* d, const atUint8* a, const atUint8* N, atUint32 n, atUint8* e, atUint32 en);
void inv(atUint8* d, atUint8* a, const atUint8* N, atUint32 n); void inv(atUint8* d, atUint8* a, const atUint8* N, atUint32 n);
} } // namespace bignum

View File

@ -1,11 +1,8 @@
#pragma once #pragma once
#include "athena/Types.hpp" #include "athena/Types.hpp"
namespace ecc namespace ecc {
{
void checkEC(atUint8* ng, atUint8* ap, atUint8* sig, atUint8* sigHash, bool& apValid, bool& ngValid); void checkEC(atUint8* ng, atUint8* ap, atUint8* sig, atUint8* sigHash, bool& apValid, bool& ngValid);
void makeECCert(atUint8* cert, atUint8* sig, const char* signer, const char* name, atUint8* priv, atUint32 keyId); void makeECCert(atUint8* cert, atUint8* sig, const char* signer, const char* name, atUint8* priv, atUint32 keyId);
void createECDSA(atUint8* R, atUint8* S, atUint8* k, atUint8* hash); void createECDSA(atUint8* R, atUint8* S, atUint8* k, atUint8* hash);
} } // namespace ecc

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +1,32 @@
#include "LZ77/LZLookupTable.hpp" #include "LZ77/LZLookupTable.hpp"
#include "LZ77/LZBase.hpp" #include "LZ77/LZBase.hpp"
LZBase::LZBase(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize) LZBase::LZBase(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize)
: m_slidingWindow(slidingWindow), : m_slidingWindow(slidingWindow)
m_readAheadBuffer(minimumMatch), , m_readAheadBuffer(minimumMatch)
m_minMatch(minimumMatch), , m_minMatch(minimumMatch)
m_blockSize(blockSize), , m_blockSize(blockSize)
m_minOffset(minimumOffset) , m_minOffset(minimumOffset) {}
{
}
void LZBase::setSlidingWindow(atInt32 slidingWindow) void LZBase::setSlidingWindow(atInt32 slidingWindow) { m_slidingWindow = slidingWindow; }
{
m_slidingWindow = slidingWindow;
}
atInt32 LZBase::slidingWindow() {return m_slidingWindow;} atInt32 LZBase::slidingWindow() { return m_slidingWindow; }
void LZBase::setReadAheadBuffer(atInt32 readAheadBuffer) void LZBase::setReadAheadBuffer(atInt32 readAheadBuffer) { m_readAheadBuffer = readAheadBuffer; }
{
m_readAheadBuffer = readAheadBuffer;
}
atInt32 LZBase::readAheadBuffer() {return m_readAheadBuffer;} atInt32 LZBase::readAheadBuffer() { return m_readAheadBuffer; }
void LZBase::setMinMatch(atInt32 minimumMatch) { m_minMatch = minimumMatch;} void LZBase::setMinMatch(atInt32 minimumMatch) { m_minMatch = minimumMatch; }
atInt32 LZBase::minMatch() {return m_minMatch;} atInt32 LZBase::minMatch() { return m_minMatch; }
void LZBase::setBlockSize(atInt32 blockSize) void LZBase::setBlockSize(atInt32 blockSize) { m_blockSize = blockSize; }
{
m_blockSize = blockSize ;
}
atInt32 LZBase::blockSize() {return m_blockSize;} atInt32 LZBase::blockSize() { return m_blockSize; }
void LZBase::setMinimumOffset(atUint32 minimumOffset) { m_minOffset = minimumOffset;} void LZBase::setMinimumOffset(atUint32 minimumOffset) { m_minOffset = minimumOffset; }
atUint32 LZBase::minimumOffset() atUint32 LZBase::minimumOffset() { return m_minOffset; }
{
return m_minOffset;
}
/* /*
DerricMc: DerricMc:
@ -54,55 +39,51 @@ atUint32 LZBase::minimumOffset()
and 17 bytes did match then 17 bytes match is return). and 17 bytes did match then 17 bytes match is return).
*/ */
LZLengthOffset LZBase::search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd) LZLengthOffset LZBase::search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd) {
{ LZLengthOffset results = {0, 0};
LZLengthOffset results = {0, 0};
//Returns negative 1 for Search failures since the current position is passed the size to be compressed
if (posPtr >= dataEnd)
{
results.length = -1;
return results;
}
atUint8* searchWindow;
//LookAheadBuffer is ReadAheadBuffer Size if there are more bytes than ReadAheadBufferSize waiting
//to be compressed else the number of remaining bytes is the LookAheadBuffer
int lookAheadBuffer_len = ((int)(dataEnd - posPtr) < m_readAheadBuffer) ? (int)(dataEnd - posPtr) : m_readAheadBuffer;
int slidingBuffer = (int)(posPtr - dataBegin) - m_slidingWindow;
if (slidingBuffer > 0)
searchWindow = dataBegin + slidingBuffer;
else
searchWindow = dataBegin;
atUint8* endPos = posPtr + lookAheadBuffer_len;
if (!((posPtr - dataBegin < 1) || (dataEnd - posPtr < m_minMatch)))
results = windowSearch(searchWindow, posPtr, endPos, posPtr - m_minOffset);
// Returns negative 1 for Search failures since the current position is passed the size to be compressed
if (posPtr >= dataEnd) {
results.length = -1;
return results; return results;
}
atUint8* searchWindow;
// LookAheadBuffer is ReadAheadBuffer Size if there are more bytes than ReadAheadBufferSize waiting
// to be compressed else the number of remaining bytes is the LookAheadBuffer
int lookAheadBuffer_len = ((int)(dataEnd - posPtr) < m_readAheadBuffer) ? (int)(dataEnd - posPtr) : m_readAheadBuffer;
int slidingBuffer = (int)(posPtr - dataBegin) - m_slidingWindow;
if (slidingBuffer > 0)
searchWindow = dataBegin + slidingBuffer;
else
searchWindow = dataBegin;
atUint8* endPos = posPtr + lookAheadBuffer_len;
if (!((posPtr - dataBegin < 1) || (dataEnd - posPtr < m_minMatch)))
results = windowSearch(searchWindow, posPtr, endPos, posPtr - m_minOffset);
return results;
} }
// Returns the full length of string2 if they are equal else
// Return the number of characters that were equal before they weren't equal
int LZBase::subMatch(const uint8_t* str1, const uint8_t* str2, const int len) {
for (int i = 0; i < len; ++i)
if (str1[i] != str2[i])
return i;
//Returns the full length of string2 if they are equal else return len;
//Return the number of characters that were equal before they weren't equal
int LZBase::subMatch(const uint8_t* str1, const uint8_t* str2, const int len)
{
for (int i = 0; i < len; ++i)
if (str1[i] != str2[i])
return i;
return len;
} }
/* /*
Normally a search for one byte is matched, then two, then three, all the way up Normally a search for one byte is matched, then two, then three, all the way up
to the size of the LookAheadBuffer. So I decided to skip the incremental search to the size of the LookAheadBuffer. So I decided to skip the incremental search
and search for the entire LookAheadBuffer and if the function doesn't find the bytes are and search for the entire LookAheadBuffer and if the function doesn't find the bytes are
equal the function return the next best match(which means if the function look for 18 bytes and they are not found, return equal the function return the next best match(which means if the function look for 18 bytes and they are not found,
the number of bytes that did match before it failed to match. The submatch is function returns the number of bytes that return the number of bytes that did match before it failed to match. The submatch is function returns the number of
were equal, which can result up to the bytes total length if both byte strings are equal. bytes that were equal, which can result up to the bytes total length if both byte strings are equal.
...[][][][][][][][][][][][]|[][][][][][][][][][][][][][] ...[][][][][][][][][][][][]|[][][][][][][][][][][][][][]
@ -112,39 +93,35 @@ Normally a search for one byte is matched, then two, then three, all the way up
Sliding Window Sliding Window
Up to 4114 bytes Up to 4114 bytes
*/ */
LZLengthOffset LZBase::windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr, atUint8* startLBPtr) LZLengthOffset LZBase::windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr,
{ atUint8* startLBPtr) {
atInt32 size = (atUint32)(endLABufferPtr - beginSearchPtr); //Size of the entire sliding window atInt32 size = (atUint32)(endLABufferPtr - beginSearchPtr); // Size of the entire sliding window
atInt32 n = (atUint32)(endLABufferPtr - searchPosPtr); atInt32 n = (atUint32)(endLABufferPtr - searchPosPtr);
LZLengthOffset result = {0, 0}; LZLengthOffset result = {0, 0};
atInt32 temp = 0; atInt32 temp = 0;
if (n > size) //If the string that is being looked for is bigger than the string that is being searched
return result;
/*This makes sure that search for the searchPosPtr can be searched if an invalid position is given
An invalid position occurs if the amount of characters to search in_beginSearchPtr is less than the size
of searchPosPtr. In other words there has to be at least n characters left in the string
to have a chance to find n characters*/
do
{
temp = subMatch(startLBPtr, searchPosPtr, n);
if (result.length < (atUint32)temp)
{
result.length = temp;
result.offset = (atInt32)(searchPosPtr - startLBPtr);
}
if (result.length == (atUint32)n)
return result;
//ReadAheadBuffer is the maximum size of a character match
}
while ((startLBPtr--) > beginSearchPtr);
if (n > size) // If the string that is being looked for is bigger than the string that is being searched
return result; return result;
}
/*This makes sure that search for the searchPosPtr can be searched if an invalid position is given
An invalid position occurs if the amount of characters to search in_beginSearchPtr is less than the size
of searchPosPtr. In other words there has to be at least n characters left in the string
to have a chance to find n characters*/
do {
temp = subMatch(startLBPtr, searchPosPtr, n);
if (result.length < (atUint32)temp) {
result.length = temp;
result.offset = (atInt32)(searchPosPtr - startLBPtr);
}
if (result.length == (atUint32)n)
return result;
// ReadAheadBuffer is the maximum size of a character match
} while ((startLBPtr--) > beginSearchPtr);
return result;
}

View File

@ -1,129 +1,116 @@
#include "LZ77/LZLookupTable.hpp" #include "LZ77/LZLookupTable.hpp"
#include <algorithm> #include <algorithm>
LZLookupTable::LZLookupTable() LZLookupTable::LZLookupTable() {
{ m_minimumMatch = 3;
m_slidingWindow = 4096;
m_lookAheadWindow = 18;
m_buffer.resize(m_minimumMatch);
}
LZLookupTable::LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow, atInt32 lookAheadWindow) {
if (minimumMatch > 0)
m_minimumMatch = minimumMatch;
else
m_minimumMatch = 3; m_minimumMatch = 3;
if (slidingWindow > 0)
m_slidingWindow = slidingWindow;
else
m_slidingWindow = 4096; m_slidingWindow = 4096;
if (lookAheadWindow > 0)
m_lookAheadWindow = lookAheadWindow;
else
m_lookAheadWindow = 18; m_lookAheadWindow = 18;
m_buffer.resize(m_minimumMatch);
m_buffer.reserve(m_minimumMatch);
} }
LZLookupTable::LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow, atInt32 lookAheadWindow) LZLookupTable::~LZLookupTable() {}
{
if (minimumMatch > 0)
m_minimumMatch = minimumMatch;
else
m_minimumMatch = 3;
if (slidingWindow > 0) void LZLookupTable::setLookAheadWindow(atInt32 lookAheadWindow) {
m_slidingWindow = slidingWindow; if (lookAheadWindow > 0)
else m_lookAheadWindow = lookAheadWindow;
m_slidingWindow = 4096; else
m_lookAheadWindow = 18;
if (lookAheadWindow > 0)
m_lookAheadWindow = lookAheadWindow;
else
m_lookAheadWindow = 18;
m_buffer.reserve(m_minimumMatch);
} }
LZLookupTable::~LZLookupTable() LZLengthOffset LZLookupTable::search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd) {
{} LZLengthOffset loPair = {0, 0};
void LZLookupTable::setLookAheadWindow(atInt32 lookAheadWindow) // Returns negative 1 for search failures since the current position is passed the size to be compressed
{ if (curPos >= dataEnd) {
if (lookAheadWindow > 0) loPair.length = -1;
m_lookAheadWindow = lookAheadWindow;
else
m_lookAheadWindow = 18;
}
LZLengthOffset LZLookupTable::search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd)
{
LZLengthOffset loPair = {0, 0};
//Returns negative 1 for search failures since the current position is passed the size to be compressed
if (curPos >= dataEnd)
{
loPair.length = -1;
return loPair;
}
std::copy(curPos, curPos + m_minimumMatch, m_buffer.begin());
int32_t currentOffset = static_cast<atInt32>(curPos - dataBegin);
//Find code
if (currentOffset > 0 && (dataEnd - curPos) >= m_minimumMatch)
{
auto elements = table.equal_range(m_buffer);
elements.second--;
elements.first--;
//Iterate over keys in reverse order. C++11 guarantees that the relative order of elements is maintained for the same key
for (auto iter = elements.second; iter != elements.first; iter--)
{
int32_t matchLength = m_minimumMatch;
int32_t lookAheadBufferLength = ((dataEnd - curPos) < m_lookAheadWindow) ? static_cast<int32_t>(dataEnd - curPos) : m_lookAheadWindow;
for (; matchLength < lookAheadBufferLength; ++matchLength)
{
if (*(dataBegin + iter->second + matchLength) != *(curPos + matchLength))
break;
}
//Store the longest match found so far into length_offset struct.
//When lengths are the same the closer offset to the lookahead buffer wins
if (loPair.length < (atUint32)matchLength)
{
loPair.length = matchLength;
loPair.offset = currentOffset - iter->second;
}
//Found the longest match so break out of loop
if (loPair.length == (atUint32)m_lookAheadWindow)
break;
}
}
//end find code
//Insert code
table.insert(std::make_pair(m_buffer, currentOffset));
for (atUint32 i = 1; i < loPair.length; i++)
{
if (dataEnd - (curPos + i) < m_minimumMatch)
break;
std::copy(curPos + i, curPos + m_minimumMatch + i, m_buffer.begin());
table.insert(std::make_pair(m_buffer, currentOffset + i));
}
//end insert code
//Delete code
int32_t slidingWindowOffset = std::max(0, currentOffset - m_slidingWindow);//Absolute offset
int32_t tablesize = static_cast<int32_t>(table.size());
for (int32_t i = 0; i < tablesize - m_slidingWindow; ++i)
{
std::copy(dataBegin + slidingWindowOffset + i, dataBegin + slidingWindowOffset + m_minimumMatch + i, m_buffer.begin());
auto elements = table.equal_range(m_buffer);
for (auto iter = elements.first; iter != elements.second; iter++)
{
if (slidingWindowOffset + i == iter->second)
{
table.erase(iter);
//There should no occurance of the map with the same value
break;
}
}
}
//end delete code
return loPair; return loPair;
//break lookupTable.cpp:109 if table.size()> 4096 }
std::copy(curPos, curPos + m_minimumMatch, m_buffer.begin());
int32_t currentOffset = static_cast<atInt32>(curPos - dataBegin);
// Find code
if (currentOffset > 0 && (dataEnd - curPos) >= m_minimumMatch) {
auto elements = table.equal_range(m_buffer);
elements.second--;
elements.first--;
// Iterate over keys in reverse order. C++11 guarantees that the relative order of elements is maintained for the
// same key
for (auto iter = elements.second; iter != elements.first; iter--) {
int32_t matchLength = m_minimumMatch;
int32_t lookAheadBufferLength =
((dataEnd - curPos) < m_lookAheadWindow) ? static_cast<int32_t>(dataEnd - curPos) : m_lookAheadWindow;
for (; matchLength < lookAheadBufferLength; ++matchLength) {
if (*(dataBegin + iter->second + matchLength) != *(curPos + matchLength))
break;
}
// Store the longest match found so far into length_offset struct.
// When lengths are the same the closer offset to the lookahead buffer wins
if (loPair.length < (atUint32)matchLength) {
loPair.length = matchLength;
loPair.offset = currentOffset - iter->second;
}
// Found the longest match so break out of loop
if (loPair.length == (atUint32)m_lookAheadWindow)
break;
}
}
// end find code
// Insert code
table.insert(std::make_pair(m_buffer, currentOffset));
for (atUint32 i = 1; i < loPair.length; i++) {
if (dataEnd - (curPos + i) < m_minimumMatch)
break;
std::copy(curPos + i, curPos + m_minimumMatch + i, m_buffer.begin());
table.insert(std::make_pair(m_buffer, currentOffset + i));
}
// end insert code
// Delete code
int32_t slidingWindowOffset = std::max(0, currentOffset - m_slidingWindow); // Absolute offset
int32_t tablesize = static_cast<int32_t>(table.size());
for (int32_t i = 0; i < tablesize - m_slidingWindow; ++i) {
std::copy(dataBegin + slidingWindowOffset + i, dataBegin + slidingWindowOffset + m_minimumMatch + i,
m_buffer.begin());
auto elements = table.equal_range(m_buffer);
for (auto iter = elements.first; iter != elements.second; iter++) {
if (slidingWindowOffset + i == iter->second) {
table.erase(iter);
// There should no occurance of the map with the same value
break;
}
}
}
// end delete code
return loPair;
// break lookupTable.cpp:109 if table.size()> 4096
} }

View File

@ -4,140 +4,125 @@
#include <cstring> #include <cstring>
LZType10::LZType10(atInt32 MinimumOffset, atInt32 SlidingWindow, atInt32 MinimumMatch, atInt32 BlockSize) LZType10::LZType10(atInt32 MinimumOffset, atInt32 SlidingWindow, atInt32 MinimumMatch, atInt32 BlockSize)
: LZBase(MinimumOffset, SlidingWindow, MinimumMatch, BlockSize) : LZBase(MinimumOffset, SlidingWindow, MinimumMatch, BlockSize) {
{ // ReadAheadBuffer is normalize between (minumum match) and(minimum match + 15) so that matches fit within
//ReadAheadBuffer is normalize between (minumum match) and(minimum match + 15) so that matches fit within // 4-bits.
//4-bits. m_readAheadBuffer = m_minMatch + 0xF;
m_readAheadBuffer = m_minMatch + 0xF;
} }
atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLength) atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLength) {
{ atUint32 encodeSize = (srcLength << 8) | (0x10);
atUint32 encodeSize = (srcLength << 8) | (0x10); encodeSize = athena::utility::LittleUint32(encodeSize); // File size needs to be written as little endian always
encodeSize = athena::utility::LittleUint32(encodeSize); //File size needs to be written as little endian always
athena::io::MemoryCopyWriter outbuf("tmp"); athena::io::MemoryCopyWriter outbuf("tmp");
outbuf.writeUint32(encodeSize); outbuf.writeUint32(encodeSize);
atUint8* ptrStart = (atUint8*)src; atUint8* ptrStart = (atUint8*)src;
atUint8* ptrEnd = (atUint8*)(src + srcLength); atUint8* ptrEnd = (atUint8*)(src + srcLength);
//At most their will be two bytes written if the bytes can be compressed. So if all bytes in the block can be compressed it would take blockSize*2 bytes // At most their will be two bytes written if the bytes can be compressed. So if all bytes in the block can be
atUint8* compressedBytes = new atUint8[m_blockSize * 2]; //Holds the compressed bytes yet to be written // compressed it would take blockSize*2 bytes
atUint8* compressedBytes = new atUint8[m_blockSize * 2]; // Holds the compressed bytes yet to be written
while (ptrStart < ptrEnd) while (ptrStart < ptrEnd) {
{ atUint8 blockLen = 0;
atUint8 blockLen = 0; // In Binary represents 1 if byte is compressed or 0 if not compressed
//In Binary represents 1 if byte is compressed or 0 if not compressed // For example 01001000 means that the second and fifth byte in the blockSize from the left is compressed
//For example 01001000 means that the second and fifth byte in the blockSize from the left is compressed atUint8* ptrBytes = compressedBytes;
atUint8* ptrBytes = compressedBytes;
for (atInt32 i = 0; i < m_blockSize; i++) for (atInt32 i = 0; i < m_blockSize; i++) {
{ // length_offset searchResult=Search(ptrStart, filedata, ptrEnd);
//length_offset searchResult=Search(ptrStart, filedata, ptrEnd); LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd);
LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd);
//If the number of bytes to be compressed is at least the size of the Minimum match // If the number of bytes to be compressed is at least the size of the Minimum match
if (searchResult.length >= (atUint32)m_minMatch) if (searchResult.length >= (atUint32)m_minMatch) {
{ // Gotta swap the bytes since system is wii is big endian and most computers are little endian
//Gotta swap the bytes since system is wii is big endian and most computers are little endian atUint16 lenOff = (((searchResult.length - m_minMatch) & 0xF) << 12) | ((searchResult.offset - 1) & 0xFFF);
atUint16 lenOff = (((searchResult.length - m_minMatch) & 0xF) << 12) | ((searchResult.offset - 1) & 0xFFF); athena::utility::BigUint16(lenOff);
athena::utility::BigUint16(lenOff);
memcpy(ptrBytes, &lenOff, sizeof(atUint16)); memcpy(ptrBytes, &lenOff, sizeof(atUint16));
ptrBytes += sizeof(atUint16); ptrBytes += sizeof(atUint16);
ptrStart += searchResult.length; ptrStart += searchResult.length;
blockLen |= (1 << (7 - i));
//Stores which of the next 8 bytes is compressed
//bit 1 for compress and bit 0 for not compressed
}
else
*ptrBytes++ = *ptrStart++;
}
outbuf.writeByte(blockLen);
outbuf.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes));
blockLen |= (1 << (7 - i));
// Stores which of the next 8 bytes is compressed
// bit 1 for compress and bit 0 for not compressed
} else
*ptrBytes++ = *ptrStart++;
} }
delete[] compressedBytes; outbuf.writeByte(blockLen);
compressedBytes = nullptr; outbuf.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes));
}
//Add zeros until the file is a multiple of 4 delete[] compressedBytes;
while ((outbuf.position() % 4) != 0) compressedBytes = nullptr;
outbuf.writeByte(0);
*dstBuf = outbuf.data(); // Add zeros until the file is a multiple of 4
outbuf.save(); while ((outbuf.position() % 4) != 0)
return (atUint32)outbuf.length(); outbuf.writeByte(0);
*dstBuf = outbuf.data();
outbuf.save();
return (atUint32)outbuf.length();
} }
atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
{ if (*(atUint8*)(src) != 0x10)
if (*(atUint8*)(src) != 0x10) return 0;
return 0;
atUint32 uncompressedSize = *(atUint32*)(src); //Size of data when it is uncompressed atUint32 uncompressedSize = *(atUint32*)(src); // Size of data when it is uncompressed
athena::utility::LittleUint32(uncompressedSize); //The compressed file has the filesize encoded in little endian athena::utility::LittleUint32(uncompressedSize); // The compressed file has the filesize encoded in little endian
uncompressedSize = uncompressedSize >> 8;//first byte is the encode flag uncompressedSize = uncompressedSize >> 8; // first byte is the encode flag
atUint8* uncompressedData = new atUint8[uncompressedSize]; atUint8* uncompressedData = new atUint8[uncompressedSize];
atUint8* outputPtr = uncompressedData; atUint8* outputPtr = uncompressedData;
atUint8* outputEndPtr = uncompressedData + uncompressedSize; atUint8* outputEndPtr = uncompressedData + uncompressedSize;
atUint8* inputPtr = (atUint8*)src + 4; atUint8* inputPtr = (atUint8*)src + 4;
atUint8* inputEndPtr = (atUint8*)src + srcLength; atUint8* inputEndPtr = (atUint8*)src + srcLength;
while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) {
{
atUint8 isCompressed = *inputPtr++; atUint8 isCompressed = *inputPtr++;
for (atUint32 i = 0; i < (atUint32)m_blockSize; i++)
{
//Checks to see if the next byte is compressed by looking
//at its binary representation - E.g 10010000
//This says that the first extracted byte and the four extracted byte is compressed
if ((isCompressed >> (7 - i)) & 0x1)
{
atUint16 lenOff;
memcpy(&lenOff, inputPtr, sizeof(atUint16));
athena::utility::BigUint16(lenOff);
inputPtr += sizeof(atUint16); //Move forward two bytes
//length offset pair has been decoded.
LZLengthOffset decoding;
decoding.length = (lenOff >> 12) + m_minMatch;
decoding.offset = static_cast<atUint16>((lenOff & 0xFFF) + 1);
if ((outputPtr - decoding.offset) < uncompressedData)
{
//If the offset to look for uncompressed is passed the current uncompresed data then the data is not compressed
delete[] uncompressedData;
uncompressedData = nullptr;
dst = nullptr;
return 0;
}
for (atUint32 j = 0; j < decoding.length; ++j)
outputPtr[j] = (outputPtr - decoding.offset)[j];
outputPtr += decoding.length;
}
else
*outputPtr++ = *inputPtr++;
if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr))
break;
for (atUint32 i = 0; i < (atUint32)m_blockSize; i++) {
// Checks to see if the next byte is compressed by looking
// at its binary representation - E.g 10010000
// This says that the first extracted byte and the four extracted byte is compressed
if ((isCompressed >> (7 - i)) & 0x1) {
atUint16 lenOff;
memcpy(&lenOff, inputPtr, sizeof(atUint16));
athena::utility::BigUint16(lenOff);
inputPtr += sizeof(atUint16); // Move forward two bytes
// length offset pair has been decoded.
LZLengthOffset decoding;
decoding.length = (lenOff >> 12) + m_minMatch;
decoding.offset = static_cast<atUint16>((lenOff & 0xFFF) + 1);
if ((outputPtr - decoding.offset) < uncompressedData) {
// If the offset to look for uncompressed is passed the current uncompresed data then the data is not
// compressed
delete[] uncompressedData;
uncompressedData = nullptr;
dst = nullptr;
return 0;
} }
for (atUint32 j = 0; j < decoding.length; ++j)
outputPtr[j] = (outputPtr - decoding.offset)[j];
outputPtr += decoding.length;
} else
*outputPtr++ = *inputPtr++;
if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr))
break;
} }
}
*dst = uncompressedData; *dst = uncompressedData;
return uncompressedSize; return uncompressedSize;
} }

View File

@ -3,233 +3,209 @@
#include <athena/MemoryWriter.hpp> #include <athena/MemoryWriter.hpp>
#include <cstring> #include <cstring>
LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize) LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize)
: LZBase(minimumOffset, slidingWindow, minimumMatch, blockSize) : LZBase(minimumOffset, slidingWindow, minimumMatch, blockSize) {
{ m_readAheadBuffer = (0xF + 0xFF + 0xFFFF + m_minMatch);
m_readAheadBuffer = (0xF + 0xFF + 0xFFFF + m_minMatch); m_lookupTable.setLookAheadWindow(m_readAheadBuffer);
m_lookupTable.setLookAheadWindow(m_readAheadBuffer);
} }
atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLength) atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
{ athena::io::MemoryCopyWriter outbuff("tmp");
athena::io::MemoryCopyWriter outbuff("tmp");
if (srcLength > 0xFFFFFF) // If length is greater than 24 bits or 16 Megs if (srcLength > 0xFFFFFF) // If length is greater than 24 bits or 16 Megs
{ {
atUint32 encodeFlag = 0x11; atUint32 encodeFlag = 0x11;
athena::utility::LittleUint32(encodeFlag); athena::utility::LittleUint32(encodeFlag);
athena::utility::LittleUint32(srcLength);//Filesize data is little endian athena::utility::LittleUint32(srcLength); // Filesize data is little endian
outbuff.writeUint32(encodeFlag); outbuff.writeUint32(encodeFlag);
outbuff.writeUint32(srcLength); outbuff.writeUint32(srcLength);
} } else {
else atUint32 encodeSize = (srcLength << 8) | (0x11);
{ athena::utility::LittleUint32(encodeSize);
atUint32 encodeSize = (srcLength << 8) | (0x11); outbuff.writeUint32(encodeSize);
athena::utility::LittleUint32(encodeSize); }
outbuff.writeUint32(encodeSize);
}
atUint8* ptrStart = (atUint8*)src; atUint8* ptrStart = (atUint8*)src;
atUint8* ptrEnd = (atUint8*)(src + srcLength); atUint8* ptrEnd = (atUint8*)(src + srcLength);
//At most their will be two bytes written if the bytes can be compressed. So if all bytes in the block can be compressed it would take blockSize*2 bytes // At most their will be two bytes written if the bytes can be compressed. So if all bytes in the block can be
atUint8* compressedBytes = new atUint8[m_blockSize * 2]; //Holds the compressed bytes yet to be written // compressed it would take blockSize*2 bytes
atUint8* compressedBytes = new atUint8[m_blockSize * 2]; // Holds the compressed bytes yet to be written
atUint8 maxTwoByteMatch = 0xF + 1; atUint8 maxTwoByteMatch = 0xF + 1;
atUint8 minThreeByteMatch = maxTwoByteMatch + 1; //Minimum Three byte match is maximum TwoByte match + 1 atUint8 minThreeByteMatch = maxTwoByteMatch + 1; // Minimum Three byte match is maximum TwoByte match + 1
atUint16 maxThreeByteMatch = 0xFF + minThreeByteMatch; atUint16 maxThreeByteMatch = 0xFF + minThreeByteMatch;
atUint16 minFourByteMatch = maxThreeByteMatch + 1; //Minimum Four byte match is maximum Three Byte match + 1 atUint16 minFourByteMatch = maxThreeByteMatch + 1; // Minimum Four byte match is maximum Three Byte match + 1
atInt32 maxFourByteMatch = 0xFFFF + minFourByteMatch; atInt32 maxFourByteMatch = 0xFFFF + minFourByteMatch;
/* /*
Normaliazation Example: If MIN_MATCH is 3 then 3 gets mapped to 2 and 16 gets mapped to 15. Normaliazation Example: If MIN_MATCH is 3 then 3 gets mapped to 2 and 16 gets mapped to 15.
17 gets mapped to 1 and 272 gets mapped to 255 17 gets mapped to 1 and 272 gets mapped to 255
273 gets mapped to 0 and 65808 gets mapped to 65535 273 gets mapped to 0 and 65808 gets mapped to 65535
A two byte match uses 4 bits A two byte match uses 4 bits
A three byte match uses 8 bits A three byte match uses 8 bits
A four byte match uses 16 bits A four byte match uses 16 bits
In each case the offset uses 12 bits In each case the offset uses 12 bits
In the two byte case the length is normalized so that the first 4 bits are numbers between between 2 and 15 In the two byte case the length is normalized so that the first 4 bits are numbers between between 2 and 15
In the three byte case the first 4 bits are 0000 In the three byte case the first 4 bits are 0000
In the four byte case the first 4 bits a 0001 In the four byte case the first 4 bits a 0001
*/ */
while (ptrStart < ptrEnd) while (ptrStart < ptrEnd) {
{ atUint8 blockSize = 0;
atUint8 blockSize = 0; // In Binary represents 1 if byte is compressed or 0 if not compressed
//In Binary represents 1 if byte is compressed or 0 if not compressed // For example 01001000 means that the second and fifth byte in the blockSize from the left is compressed
//For example 01001000 means that the second and fifth byte in the blockSize from the left is compressed atUint8* ptrBytes = compressedBytes;
atUint8* ptrBytes = compressedBytes;
for (atInt32 i = 0; i < m_blockSize; i++) for (atInt32 i = 0; i < m_blockSize; i++) {
{ // length_offset searchResult=Search(filedata,ptrStart,ptrEnd);
//length_offset searchResult=Search(filedata,ptrStart,ptrEnd); LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd);
LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd);
//If the number of bytes to be compressed is at least the size of the Minimum match // If the number of bytes to be compressed is at least the size of the Minimum match
if (searchResult.length >= (atUint32)m_minMatch) if (searchResult.length >= (atUint32)m_minMatch) {
{ // Gotta swap the bytes since system is wii is big endian and most computers are little endian
//Gotta swap the bytes since system is wii is big endian and most computers are little endian
if (searchResult.length <= maxTwoByteMatch)
{
atUint16 lenOff = ((((searchResult.length - 1) & 0xF) << 12) | //Bits 15-12
((searchResult.offset - 1) & 0xFFF) //Bits 11-0
);
athena::utility::BigUint16(lenOff);
memcpy(ptrBytes, &lenOff, 2);
ptrBytes += 2;
}
else if (searchResult.length <= maxThreeByteMatch)
{
atUint32 lenOff = ((((searchResult.length - minThreeByteMatch) & 0xFF) << 12) | //Bits 20-12
((searchResult.offset - 1) & 0xFFF) //Bits 11-0
);
athena::utility::BigUint32(lenOff);
memcpy(ptrBytes, (atUint8*)&lenOff + 1, 3); //Make sure to copy the lower 24 bits. 0x12345678- This statement copies 0x123456
ptrBytes += 3;
}
else if (searchResult.length <= (atUint32)maxFourByteMatch)
{
atUint32 lenOff = ((1 << 28) | //Bits 31-28 Flag to say that this is four bytes
(((searchResult.length - minFourByteMatch) & 0xFFFF) << 12) | //Bits 28-12
((searchResult.offset - 1) & 0xFFF) //Bits 11-0
);
athena::utility::BigUint32(lenOff);
memcpy(ptrBytes, &lenOff, 4);
ptrBytes += 4;
}
ptrStart += searchResult.length;
blockSize |= (1 << (7 - i));
//Stores which of the next 8 bytes is compressed
//bit 1 for compress and bit 0 for not compressed
}
else
*ptrBytes++ = *ptrStart++;
if (searchResult.length <= maxTwoByteMatch) {
atUint16 lenOff = ((((searchResult.length - 1) & 0xF) << 12) | // Bits 15-12
((searchResult.offset - 1) & 0xFFF) // Bits 11-0
);
athena::utility::BigUint16(lenOff);
memcpy(ptrBytes, &lenOff, 2);
ptrBytes += 2;
} else if (searchResult.length <= maxThreeByteMatch) {
atUint32 lenOff = ((((searchResult.length - minThreeByteMatch) & 0xFF) << 12) | // Bits 20-12
((searchResult.offset - 1) & 0xFFF) // Bits 11-0
);
athena::utility::BigUint32(lenOff);
memcpy(ptrBytes, (atUint8*)&lenOff + 1,
3); // Make sure to copy the lower 24 bits. 0x12345678- This statement copies 0x123456
ptrBytes += 3;
} else if (searchResult.length <= (atUint32)maxFourByteMatch) {
atUint32 lenOff = ((1 << 28) | // Bits 31-28 Flag to say that this is four bytes
(((searchResult.length - minFourByteMatch) & 0xFFFF) << 12) | // Bits 28-12
((searchResult.offset - 1) & 0xFFF) // Bits 11-0
);
athena::utility::BigUint32(lenOff);
memcpy(ptrBytes, &lenOff, 4);
ptrBytes += 4;
} }
outbuff.writeByte(blockSize); ptrStart += searchResult.length;
outbuff.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes));
blockSize |= (1 << (7 - i));
// Stores which of the next 8 bytes is compressed
// bit 1 for compress and bit 0 for not compressed
} else
*ptrBytes++ = *ptrStart++;
} }
delete []compressedBytes; outbuff.writeByte(blockSize);
compressedBytes = NULL; outbuff.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes));
}
//Add zeros until the file is a multiple of 4 delete[] compressedBytes;
while ((outbuff.position() % 4) != 0) compressedBytes = NULL;
outbuff.writeByte(0);
*dst = outbuff.data(); // Add zeros until the file is a multiple of 4
return (atUint32)outbuff.length(); while ((outbuff.position() % 4) != 0)
outbuff.writeByte(0);
*dst = outbuff.data();
return (atUint32)outbuff.length();
} }
atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
{ if (*(atUint8*)(src) != 0x11)
if (*(atUint8*)(src) != 0x11) return 0;
return 0;
atUint32 uncompressedLen = *(atUint32*)(src); atUint32 uncompressedLen = *(atUint32*)(src);
athena::utility::LittleUint32(uncompressedLen);//The compressed file has the filesize encoded in little endian athena::utility::LittleUint32(uncompressedLen); // The compressed file has the filesize encoded in little endian
uncompressedLen = uncompressedLen >> 8; //First byte is the encode flag uncompressedLen = uncompressedLen >> 8; // First byte is the encode flag
atUint32 currentOffset = 4; atUint32 currentOffset = 4;
if (uncompressedLen == 0) //If the filesize var is zero then the true filesize is over 14MB and must be read in from the next 4 bytes if (uncompressedLen ==
{ 0) // If the filesize var is zero then the true filesize is over 14MB and must be read in from the next 4 bytes
atUint32 filesize = *(atUint32*)(src + 4); {
filesize = athena::utility::LittleUint32(filesize); atUint32 filesize = *(atUint32*)(src + 4);
currentOffset += 4; filesize = athena::utility::LittleUint32(filesize);
} currentOffset += 4;
}
atUint8* uncompressedData = new atUint8[uncompressedLen]; atUint8* uncompressedData = new atUint8[uncompressedLen];
atUint8* outputPtr = uncompressedData; atUint8* outputPtr = uncompressedData;
atUint8* outputEndPtr = uncompressedData + uncompressedLen; atUint8* outputEndPtr = uncompressedData + uncompressedLen;
atUint8* inputPtr = (atUint8*)src + currentOffset; atUint8* inputPtr = (atUint8*)src + currentOffset;
atUint8* inputEndPtr = (atUint8*)src + srcLength; atUint8* inputEndPtr = (atUint8*)src + srcLength;
LZLengthOffset decoding; LZLengthOffset decoding;
atUint8 maxTwoByteMatch = 0xF + 1; atUint8 maxTwoByteMatch = 0xF + 1;
atUint8 threeByteDenorm = maxTwoByteMatch + 1; //Amount to add to length when compression is 3 bytes atUint8 threeByteDenorm = maxTwoByteMatch + 1; // Amount to add to length when compression is 3 bytes
atUint16 maxThreeByteMatch = 0xFF + threeByteDenorm; atUint16 maxThreeByteMatch = 0xFF + threeByteDenorm;
atUint16 fourByteDenorm = maxThreeByteMatch + 1; atUint16 fourByteDenorm = maxThreeByteMatch + 1;
while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) {
{
atUint8 isCompressed = *inputPtr++; atUint8 isCompressed = *inputPtr++;
for (atInt32 i = 0; i < m_blockSize; i++) for (atInt32 i = 0; i < m_blockSize; i++) {
// Checks to see if the next byte is compressed by looking
// at its binary representation - E.g 10010000
// This says that the first extracted byte and the four extracted byte is compressed
if ((isCompressed >> (7 - i)) & 0x1) {
atUint8 metaDataSize = *inputPtr >> 4; // Look at the top 4 bits
if (metaDataSize >= 2) // Two Bytes of Length/Offset MetaData
{ {
//Checks to see if the next byte is compressed by looking atUint16 lenOff = 0;
//at its binary representation - E.g 10010000 memcpy(&lenOff, inputPtr, 2);
//This says that the first extracted byte and the four extracted byte is compressed inputPtr += 2;
if ((isCompressed >> (7 - i)) & 0x1) athena::utility::BigUint16(lenOff);
{ decoding.length = (lenOff >> 12) + 1;
atUint8 metaDataSize = *inputPtr >> 4; //Look at the top 4 bits decoding.offset = (lenOff & 0xFFF) + 1;
} else if (metaDataSize == 0) // Three Bytes of Length/Offset MetaData
if (metaDataSize >= 2) //Two Bytes of Length/Offset MetaData {
{ atUint32 lenOff = 0;
atUint16 lenOff = 0; memcpy((atUint8*)&lenOff + 1, inputPtr, 3);
memcpy(&lenOff, inputPtr, 2); inputPtr += 3;
inputPtr += 2; athena::utility::BigUint32(lenOff);
athena::utility::BigUint16(lenOff); decoding.length = (lenOff >> 12) + threeByteDenorm;
decoding.length = (lenOff >> 12) + 1; decoding.offset = (lenOff & 0xFFF) + 1;
decoding.offset = (lenOff & 0xFFF) + 1; } else if (metaDataSize == 1) // Four Bytes of Length/Offset MetaData
} {
else if (metaDataSize == 0) //Three Bytes of Length/Offset MetaData atUint32 lenOff = 0;
{ memcpy(&lenOff, inputPtr, 4);
atUint32 lenOff = 0; inputPtr += 4;
memcpy((atUint8*)&lenOff + 1, inputPtr, 3); athena::utility::BigUint32(lenOff);
inputPtr += 3;
athena::utility::BigUint32(lenOff);
decoding.length = (lenOff >> 12) + threeByteDenorm;
decoding.offset = (lenOff & 0xFFF) + 1;
}
else if (metaDataSize == 1) //Four Bytes of Length/Offset MetaData
{
atUint32 lenOff = 0;
memcpy(&lenOff, inputPtr, 4);
inputPtr += 4;
athena::utility::BigUint32(lenOff);
decoding.length = ((lenOff >> 12) & 0xFFFF) + fourByteDenorm; //Gets rid of the Four byte flag
decoding.offset = (lenOff & 0xFFF) + 1;
}
else
{
delete[] uncompressedData;
uncompressedData = nullptr;
return 0;
}
if ((outputPtr - decoding.offset) < uncompressedData) //If the offset to look for uncompressed is passed the current uncompresed data then the data is not compressed
{
delete []uncompressedData;
return 0;
}
for (atUint32 j = 0; j < decoding.length; ++j)
outputPtr[j] = (outputPtr - decoding.offset)[j];
outputPtr += decoding.length;
}
else
*outputPtr++ = *inputPtr++;
if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr))
break;
decoding.length = ((lenOff >> 12) & 0xFFFF) + fourByteDenorm; // Gets rid of the Four byte flag
decoding.offset = (lenOff & 0xFFF) + 1;
} else {
delete[] uncompressedData;
uncompressedData = nullptr;
return 0;
} }
if ((outputPtr - decoding.offset) < uncompressedData) // If the offset to look for uncompressed is passed the
// current uncompresed data then the data is not compressed
{
delete[] uncompressedData;
return 0;
}
for (atUint32 j = 0; j < decoding.length; ++j)
outputPtr[j] = (outputPtr - decoding.offset)[j];
outputPtr += decoding.length;
} else
*outputPtr++ = *inputPtr++;
if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr))
break;
} }
}
*dst = uncompressedData; *dst = uncompressedData;
return uncompressedLen; return uncompressedLen;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,45 +1,30 @@
#include "athena/ALTTPFile.hpp" #include "athena/ALTTPFile.hpp"
#include "athena/ALTTPQuest.hpp" #include "athena/ALTTPQuest.hpp"
namespace athena namespace athena {
{ ALTTPFile::ALTTPFile() {}
ALTTPFile::ALTTPFile()
{}
ALTTPFile::ALTTPFile(std::vector<ALTTPQuest*> quests, std::vector<ALTTPQuest*> backup) ALTTPFile::ALTTPFile(std::vector<ALTTPQuest*> quests, std::vector<ALTTPQuest*> backup)
: m_quests(quests) : m_quests(quests), m_backup(backup) {}
, m_backup(backup)
{ void ALTTPFile::setQuest(atUint32 id, ALTTPQuest* val) {
if (id > m_quests.size()) {
atWarning("index out of range");
return;
}
m_quests[id] = val;
} }
void ALTTPFile::setQuest(atUint32 id, ALTTPQuest* val) std::vector<ALTTPQuest*> ALTTPFile::questList() const { return m_quests; }
{ ALTTPQuest* ALTTPFile::quest(atUint32 id) const {
if (id > m_quests.size()) if (id > m_quests.size()) {
{ atWarning("index out of range");
atWarning("index out of range"); return nullptr;
return; }
}
m_quests[id] = val; return m_quests[id];
} }
std::vector<ALTTPQuest*> ALTTPFile::questList() const atUint32 ALTTPFile::questCount() const { return (atUint32)m_quests.size(); }
{ } // namespace athena
return m_quests;
}
ALTTPQuest* ALTTPFile::quest(atUint32 id) const
{
if (id > m_quests.size())
{
atWarning("index out of range");
return nullptr;
}
return m_quests[id];
}
atUint32 ALTTPFile::questCount() const
{
return (atUint32)m_quests.size();
}
} // zelda

View File

@ -4,233 +4,215 @@
#include <iostream> #include <iostream>
#include "athena/Global.hpp" #include "athena/Global.hpp"
namespace athena::io namespace athena::io {
{
ALTTPFileReader::ALTTPFileReader(atUint8* data, atUint64 length) ALTTPFileReader::ALTTPFileReader(atUint8* data, atUint64 length) : MemoryCopyReader(data, length) {}
: MemoryCopyReader(data, length)
{
}
ALTTPFileReader::ALTTPFileReader(const std::string& filename) ALTTPFileReader::ALTTPFileReader(const std::string& filename) : MemoryCopyReader(filename) {}
: MemoryCopyReader(filename)
{
}
ALTTPFile* ALTTPFileReader::readFile() ALTTPFile* ALTTPFileReader::readFile() {
{ std::vector<ALTTPQuest*> quests;
std::vector<ALTTPQuest*> quests; std::vector<ALTTPQuest*> backup;
std::vector<ALTTPQuest*> backup;
for (atUint32 i = 0; i < 6; i++) for (atUint32 i = 0; i < 6; i++) {
{ // Temporary values to use for each save
// Temporary values to use for each save ALTTPQuest* quest = new ALTTPQuest();
ALTTPQuest* quest = new ALTTPQuest(); std::vector<ALTTPRoomFlags*> roomFlags;
std::vector<ALTTPRoomFlags*> roomFlags; std::vector<ALTTPOverworldEvent*> owEvents;
std::vector<ALTTPOverworldEvent*> owEvents; std::vector<atUint8> dungeonKeys;
std::vector<atUint8> dungeonKeys; std::vector<atUint8> oldmanFlags;
std::vector<atUint8> oldmanFlags; std::vector<atUint8> unknown1;
std::vector<atUint8> unknown1; std::vector<atUint16> playerName;
std::vector<atUint16> playerName; std::vector<atUint16> dungeonDeaths;
std::vector<atUint16> dungeonDeaths;
int j = 0x140; int j = 0x140;
while ((j--) > 0) while ((j--) > 0) {
{ roomFlags.push_back(readRoomFlags());
roomFlags.push_back(readRoomFlags());
}
quest->setRoomFlags(roomFlags);
j = 0x0C0;
while ((j--) > 0)
owEvents.push_back(readOverworldEvent());
quest->setOverworldEvents(owEvents);
quest->setInventory(*(ALTTPInventory*)readBytes(sizeof(ALTTPInventory)).get());
quest->setRupeeMax(readUint16());
quest->setRupeeCurrent(readUint16());
quest->setCompasses(readDungeonFlags());
quest->setBigKeys(readDungeonFlags());
quest->setDungeonMaps(readDungeonFlags());
quest->setWishingPond(readUint16());
quest->setHealthMax(readByte());
quest->setHealth(readByte());
quest->setMagicPower(readByte());
quest->setKeys(readByte());
quest->setBombUpgrades(readByte());
quest->setArrowUpgrades(readByte());
quest->setHealthFiller(readByte());
quest->setMagicFiller(readByte());
atUint8 pendantsByte = readUByte();
ALTTPPendants pendants;
pendants.Courage = pendantsByte & 1;
pendants.Wisdom = (pendantsByte >> 1) & 1;
pendants.Power = (pendantsByte >> 2) & 1;
pendants.Unused1 = false;
pendants.Unused2 = false;
pendants.Unused3 = false;
pendants.Unused4 = false;
pendants.Unused5 = false;
quest->setPendants(pendants);
quest->setBombFiller(readByte());
quest->setArrowFiller(readByte());
quest->setArrows(readByte());
seek(1);
atUint8 abilitiesByte = readUByte();
ALTTPAbilities abilities;
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*)readBytes(sizeof(ALTTPCrystals)).get());
quest->setMagicUsage(*(ALTTPMagicUsage*)readBytes(sizeof(ALTTPMagicUsage)).get());
j = 0x10;
while ((j--) > 0)
{
dungeonKeys.push_back(readByte());
}
quest->setDungeonKeys(dungeonKeys);
seek(0x039);
quest->setProgressIndicator((ALTTPProgressIndicator)readByte());
quest->setProgressFlags1(*(ALTTPProgressFlags1*)readBytes(sizeof(ALTTPProgressFlags1)).get());
quest->setMapIcon((ALTTPMapIcon)readByte());
quest->setStartLocation((ALTTPStartLocation)readByte());
quest->setProgressFlags2(*(ALTTPProgressFlags2*)readBytes(sizeof(ALTTPProgressFlags2)).get());
quest->setLightDarkWorldIndicator(*(ALTTPLightDarkWorldIndicator*)readBytes(1).get());
seek(1);
quest->setTagAlong((ALTTPTagAlong)readByte());
j = 6;
while ((j--) > 0)
{
oldmanFlags.push_back(readByte());
}
quest->setOldManFlags(oldmanFlags);
quest->setBombFlag(readByte());
j = 5;
while ((j--) > 0)
{
unknown1.push_back(readByte());
}
quest->setUnknown1(unknown1);
j = 6;
while ((j--) > 0)
{
playerName.push_back(readUint16());
}
quest->setPlayerName(playerName);
quest->setValid((readUint16() == 0x55AA));
j = 0x0D;
while ((j--) > 0)
{
dungeonDeaths.push_back(readUint16());
}
quest->setDungeonDeathTotals(dungeonDeaths);
quest->setUnknown2(readUint16());
quest->setDeathSaveCount(readUint16());
quest->setPostGameDeathCounter(readInt16());
seek(0xF7);
quest->setChecksum(readUint16());
if (i < 3)
quests.push_back(quest);
else
backup.push_back(quest);
} }
return new ALTTPFile(quests, backup); quest->setRoomFlags(roomFlags);
j = 0x0C0;
while ((j--) > 0)
owEvents.push_back(readOverworldEvent());
quest->setOverworldEvents(owEvents);
quest->setInventory(*(ALTTPInventory*)readBytes(sizeof(ALTTPInventory)).get());
quest->setRupeeMax(readUint16());
quest->setRupeeCurrent(readUint16());
quest->setCompasses(readDungeonFlags());
quest->setBigKeys(readDungeonFlags());
quest->setDungeonMaps(readDungeonFlags());
quest->setWishingPond(readUint16());
quest->setHealthMax(readByte());
quest->setHealth(readByte());
quest->setMagicPower(readByte());
quest->setKeys(readByte());
quest->setBombUpgrades(readByte());
quest->setArrowUpgrades(readByte());
quest->setHealthFiller(readByte());
quest->setMagicFiller(readByte());
atUint8 pendantsByte = readUByte();
ALTTPPendants pendants;
pendants.Courage = pendantsByte & 1;
pendants.Wisdom = (pendantsByte >> 1) & 1;
pendants.Power = (pendantsByte >> 2) & 1;
pendants.Unused1 = false;
pendants.Unused2 = false;
pendants.Unused3 = false;
pendants.Unused4 = false;
pendants.Unused5 = false;
quest->setPendants(pendants);
quest->setBombFiller(readByte());
quest->setArrowFiller(readByte());
quest->setArrows(readByte());
seek(1);
atUint8 abilitiesByte = readUByte();
ALTTPAbilities abilities;
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*)readBytes(sizeof(ALTTPCrystals)).get());
quest->setMagicUsage(*(ALTTPMagicUsage*)readBytes(sizeof(ALTTPMagicUsage)).get());
j = 0x10;
while ((j--) > 0) {
dungeonKeys.push_back(readByte());
}
quest->setDungeonKeys(dungeonKeys);
seek(0x039);
quest->setProgressIndicator((ALTTPProgressIndicator)readByte());
quest->setProgressFlags1(*(ALTTPProgressFlags1*)readBytes(sizeof(ALTTPProgressFlags1)).get());
quest->setMapIcon((ALTTPMapIcon)readByte());
quest->setStartLocation((ALTTPStartLocation)readByte());
quest->setProgressFlags2(*(ALTTPProgressFlags2*)readBytes(sizeof(ALTTPProgressFlags2)).get());
quest->setLightDarkWorldIndicator(*(ALTTPLightDarkWorldIndicator*)readBytes(1).get());
seek(1);
quest->setTagAlong((ALTTPTagAlong)readByte());
j = 6;
while ((j--) > 0) {
oldmanFlags.push_back(readByte());
}
quest->setOldManFlags(oldmanFlags);
quest->setBombFlag(readByte());
j = 5;
while ((j--) > 0) {
unknown1.push_back(readByte());
}
quest->setUnknown1(unknown1);
j = 6;
while ((j--) > 0) {
playerName.push_back(readUint16());
}
quest->setPlayerName(playerName);
quest->setValid((readUint16() == 0x55AA));
j = 0x0D;
while ((j--) > 0) {
dungeonDeaths.push_back(readUint16());
}
quest->setDungeonDeathTotals(dungeonDeaths);
quest->setUnknown2(readUint16());
quest->setDeathSaveCount(readUint16());
quest->setPostGameDeathCounter(readInt16());
seek(0xF7);
quest->setChecksum(readUint16());
if (i < 3)
quests.push_back(quest);
else
backup.push_back(quest);
}
return new ALTTPFile(quests, backup);
} }
ALTTPRoomFlags* ALTTPFileReader::readRoomFlags() ALTTPRoomFlags* ALTTPFileReader::readRoomFlags() {
{ ALTTPRoomFlags* flags = new ALTTPRoomFlags;
ALTTPRoomFlags* flags = new ALTTPRoomFlags; atUint8 flagsByte = readUByte();
atUint8 flagsByte = readUByte(); flags->Chest1 = flagsByte & 1;
flags->Chest1 = flagsByte & 1; flags->Chest2 = (flagsByte >> 1) & 1;
flags->Chest2 = (flagsByte >> 1) & 1; flags->Chest3 = (flagsByte >> 2) & 1;
flags->Chest3 = (flagsByte >> 2) & 1; flags->Chest4 = (flagsByte >> 3) & 1;
flags->Chest4 = (flagsByte >> 3) & 1; flags->Quadrant1 = (flagsByte >> 4) & 1;
flags->Quadrant1 = (flagsByte >> 4) & 1; flags->Quadrant2 = (flagsByte >> 5) & 1;
flags->Quadrant2 = (flagsByte >> 5) & 1; flags->Quadrant3 = (flagsByte >> 6) & 1;
flags->Quadrant3 = (flagsByte >> 6) & 1; flags->Quadrant4 = (flagsByte >> 7) & 1;
flags->Quadrant4 = (flagsByte >> 7) & 1; flagsByte = readUByte();
flagsByte = readUByte(); flags->Door1 = flagsByte & 1;
flags->Door1 = flagsByte & 1; flags->Door2 = (flagsByte >> 1) & 1;
flags->Door2 = (flagsByte >> 1) & 1; flags->Door3 = (flagsByte >> 2) & 1;
flags->Door3 = (flagsByte >> 2) & 1; flags->Door4 = (flagsByte >> 3) & 1;
flags->Door4 = (flagsByte >> 3) & 1; flags->BossBattleWon = (flagsByte >> 4) & 1;
flags->BossBattleWon = (flagsByte >> 4) & 1; flags->Key = (flagsByte >> 5) & 1;
flags->Key = (flagsByte >> 5) & 1; flags->KeyOrChest = (flagsByte >> 6) & 1;
flags->KeyOrChest = (flagsByte >> 6) & 1; flags->ChestOrTile = (flagsByte >> 7) & 1;
flags->ChestOrTile = (flagsByte >> 7) & 1;
return flags; return flags;
} }
ALTTPOverworldEvent* ALTTPFileReader::readOverworldEvent() ALTTPOverworldEvent* ALTTPFileReader::readOverworldEvent() {
{ ALTTPOverworldEvent* event = new ALTTPOverworldEvent;
ALTTPOverworldEvent* event = new ALTTPOverworldEvent; atUint8 flagsByte = readUByte();
atUint8 flagsByte = readUByte(); event->Unused1 = flagsByte & 1;
event->Unused1 = flagsByte & 1; event->HeartPiece = (flagsByte >> 1) & 1;
event->HeartPiece = (flagsByte >> 1) & 1; event->Overlay = (flagsByte >> 2) & 1;
event->Overlay = (flagsByte >> 2) & 1; event->Unused2 = (flagsByte >> 3) & 1;
event->Unused2 = (flagsByte >> 3) & 1; event->Unused3 = (flagsByte >> 4) & 1;
event->Unused3 = (flagsByte >> 4) & 1; event->Unused4 = (flagsByte >> 5) & 1;
event->Unused4 = (flagsByte >> 5) & 1; event->Set = (flagsByte >> 6) & 1;
event->Set = (flagsByte >> 6) & 1; event->Unused5 = (flagsByte >> 7) & 1;
event->Unused5 = (flagsByte >> 7) & 1; return event;
return event;
} }
ALTTPDungeonItemFlags ALTTPFileReader::readDungeonFlags() ALTTPDungeonItemFlags ALTTPFileReader::readDungeonFlags() {
{ ALTTPDungeonItemFlags flags;
ALTTPDungeonItemFlags flags; atUint8 flagsByte = readUByte();
atUint8 flagsByte = readUByte(); flags.Unused1 = flagsByte & 1;
flags.Unused1 = flagsByte & 1; flags.Unused2 = (flagsByte >> 1) & 1;
flags.Unused2 = (flagsByte >> 1) & 1; flags.GanonsTower = (flagsByte >> 2) & 1;
flags.GanonsTower = (flagsByte >> 2) & 1; flags.TurtleRock = (flagsByte >> 3) & 1;
flags.TurtleRock = (flagsByte >> 3) & 1; flags.GargoylesDomain = (flagsByte >> 4) & 1;
flags.GargoylesDomain = (flagsByte >> 4) & 1; flags.TowerOfHera = (flagsByte >> 5) & 1;
flags.TowerOfHera = (flagsByte >> 5) & 1; flags.IcePalace = (flagsByte >> 6) & 1;
flags.IcePalace = (flagsByte >> 6) & 1; flags.SkullWoods = (flagsByte >> 7) & 1;
flags.SkullWoods = (flagsByte >> 7) & 1; flagsByte = readUByte();
flagsByte = readUByte(); flags.MiseryMire = flagsByte & 1;
flags.MiseryMire = flagsByte & 1; flags.DarkPalace = (flagsByte >> 1) & 1;
flags.DarkPalace = (flagsByte >> 1) & 1; flags.SwampPalace = (flagsByte >> 2) & 1;
flags.SwampPalace = (flagsByte >> 2) & 1; flags.HyruleCastle2 = (flagsByte >> 3) & 1;
flags.HyruleCastle2 = (flagsByte >> 3) & 1; flags.DesertPalace = (flagsByte >> 4) & 1;
flags.DesertPalace = (flagsByte >> 4) & 1; flags.EasternPalace = (flagsByte >> 5) & 1;
flags.EasternPalace = (flagsByte >> 5) & 1; flags.HyruleCastle = (flagsByte >> 6) & 1;
flags.HyruleCastle = (flagsByte >> 6) & 1; flags.SewerPassage = (flagsByte >> 7) & 1;
flags.SewerPassage = (flagsByte >> 7) & 1;
atDebug("%x %x", flags.flags1, flags.flags2); atDebug("%x %x", flags.flags1, flags.flags2);
return flags; return flags;
} }
} // io } // namespace athena::io

View File

@ -3,221 +3,204 @@
#include "athena/ALTTPQuest.hpp" #include "athena/ALTTPQuest.hpp"
#include <iostream> #include <iostream>
namespace athena namespace athena {
{
namespace io namespace io {
{
ALTTPFileWriter::ALTTPFileWriter(atUint8* data, atUint64 length) ALTTPFileWriter::ALTTPFileWriter(atUint8* data, atUint64 length) : MemoryCopyWriter(data, length) {}
: MemoryCopyWriter(data, length)
{
}
ALTTPFileWriter::ALTTPFileWriter(const std::string& filename) ALTTPFileWriter::ALTTPFileWriter(const std::string& filename) : MemoryCopyWriter(filename) {}
: MemoryCopyWriter(filename)
{
}
void ALTTPFileWriter::writeFile(ALTTPFile* file) void ALTTPFileWriter::writeFile(ALTTPFile* file) {
{ ALTTPQuest* quest = NULL;
ALTTPQuest* quest = NULL;
for (atUint32 i = 0; i < 6; i++) for (atUint32 i = 0; i < 6; i++) {
{ if (i < 3)
if (i < 3) quest = file->quest(i);
quest = file->quest(i); else
else quest = file->quest(i - 3);
quest = file->quest(i - 3);
for (int j = 0; j < 0x140; j++) for (int j = 0; j < 0x140; j++) {
{ writeRoomFlags(quest->roomFlags(j));
writeRoomFlags(quest->roomFlags(j));
}
for (int j = 0; j < 0x0C0; j++)
{
writeOverworldEvent(quest->overworldEvent(j));
}
writeBytes((atInt8*)&quest->inventory(), sizeof(ALTTPInventory));
writeUint16(quest->rupeeMax());
writeUint16(quest->rupeeCurrent());
writeDungeonItems(quest->compasses());
writeDungeonItems(quest->bigKeys());
writeDungeonItems(quest->dungeonMaps());
writeUint16(quest->wishingPond());
writeByte(quest->healthMax());
writeByte(quest->health());
writeByte(quest->magicPower());
writeByte(quest->keys());
writeByte(quest->bombUpgrades());
writeByte(quest->arrowUpgrades());
writeByte(quest->healthFiller());
writeByte(quest->magicFiller());
ALTTPPendants pendants = quest->pendants();
atUint8 pendantsByte = 0;
pendantsByte |= pendants.Courage;
pendantsByte |= pendants.Wisdom << 1;
pendantsByte |= pendants.Power << 2;
writeUByte(pendantsByte);
writeByte(quest->bombFiller());
writeByte(quest->arrowFiller());
writeByte(quest->arrows());
seek(1);
ALTTPAbilities abilities = quest->abilityFlags();
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;
writeUByte(abilitiesByte);
ALTTPCrystals crystals = quest->crystals();
writeBytes((atInt8*)&crystals, sizeof(ALTTPCrystals));
ALTTPMagicUsage magicUsage = quest->magicUsage();
writeBytes((atInt8*)&magicUsage, sizeof(ALTTPMagicUsage));
for (int j = 0; j < 0x010; j++)
writeByte(quest->dungeonKeys(j));
seek(0x039);
writeByte((atInt8)quest->progressIndicator());
ALTTPProgressFlags1 progress1 = quest->progressFlags1();
writeBytes((atInt8*)&progress1, sizeof(ALTTPProgressFlags1));
writeByte(quest->mapIcon());
writeByte(quest->startLocation());
ALTTPProgressFlags2 progress2 = quest->progressFlags2();
writeBytes((atInt8*)&progress2, sizeof(ALTTPProgressFlags2));
ALTTPLightDarkWorldIndicator indicator = quest->lightDarkWorldIndicator();
writeBytes((atInt8*)&indicator, 1);
seek(1);
writeByte(quest->tagAlong());
for (int j = 0; j < 6; j++)
writeByte(quest->oldManFlag(j));
writeByte(quest->bombFlag());
for (int j = 0; j < 5; j++)
writeByte(quest->unknown1(j));
for (int j = 0; j < 6; j++)
writeUint16(quest->playerName()[j]);
writeUint16((quest->valid() == true ? 0x55AA : 0));
for (int j = 0; j < 0x0D; j++)
writeUint16(quest->dungeonDeathTotal(j));
writeUint16(quest->unknown2());
writeUint16(quest->deathSaveCount());
writeUint16(quest->postGameDeathCounter());
seek(0xF7);
writeUint16(calculateChecksum(i));
} }
for (int j = 0; j < 0x0C0; j++) {
writeOverworldEvent(quest->overworldEvent(j));
}
writeBytes((atInt8*)&quest->inventory(), sizeof(ALTTPInventory));
writeUint16(quest->rupeeMax());
writeUint16(quest->rupeeCurrent());
writeDungeonItems(quest->compasses());
writeDungeonItems(quest->bigKeys());
writeDungeonItems(quest->dungeonMaps());
writeUint16(quest->wishingPond());
writeByte(quest->healthMax());
writeByte(quest->health());
writeByte(quest->magicPower());
writeByte(quest->keys());
writeByte(quest->bombUpgrades());
writeByte(quest->arrowUpgrades());
writeByte(quest->healthFiller());
writeByte(quest->magicFiller());
ALTTPPendants pendants = quest->pendants();
atUint8 pendantsByte = 0;
pendantsByte |= pendants.Courage;
pendantsByte |= pendants.Wisdom << 1;
pendantsByte |= pendants.Power << 2;
writeUByte(pendantsByte);
writeByte(quest->bombFiller());
writeByte(quest->arrowFiller());
writeByte(quest->arrows());
seek(1);
ALTTPAbilities abilities = quest->abilityFlags();
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;
writeUByte(abilitiesByte);
ALTTPCrystals crystals = quest->crystals();
writeBytes((atInt8*)&crystals, sizeof(ALTTPCrystals));
ALTTPMagicUsage magicUsage = quest->magicUsage();
writeBytes((atInt8*)&magicUsage, sizeof(ALTTPMagicUsage));
for (int j = 0; j < 0x010; j++)
writeByte(quest->dungeonKeys(j));
seek(0x039);
writeByte((atInt8)quest->progressIndicator());
ALTTPProgressFlags1 progress1 = quest->progressFlags1();
writeBytes((atInt8*)&progress1, sizeof(ALTTPProgressFlags1));
writeByte(quest->mapIcon());
writeByte(quest->startLocation());
ALTTPProgressFlags2 progress2 = quest->progressFlags2();
writeBytes((atInt8*)&progress2, sizeof(ALTTPProgressFlags2));
ALTTPLightDarkWorldIndicator indicator = quest->lightDarkWorldIndicator();
writeBytes((atInt8*)&indicator, 1);
seek(1);
writeByte(quest->tagAlong());
for (int j = 0; j < 6; j++)
writeByte(quest->oldManFlag(j));
writeByte(quest->bombFlag());
for (int j = 0; j < 5; j++)
writeByte(quest->unknown1(j));
for (int j = 0; j < 6; j++)
writeUint16(quest->playerName()[j]);
writeUint16((quest->valid() == true ? 0x55AA : 0));
for (int j = 0; j < 0x0D; j++)
writeUint16(quest->dungeonDeathTotal(j));
writeUint16(quest->unknown2());
writeUint16(quest->deathSaveCount());
writeUint16(quest->postGameDeathCounter());
seek(0xF7);
writeUint16(calculateChecksum(i));
}
} }
void ALTTPFileWriter::writeRoomFlags(ALTTPRoomFlags* flags) void ALTTPFileWriter::writeRoomFlags(ALTTPRoomFlags* flags) {
{ atUint8 flagsByte = 0;
atUint8 flagsByte = 0; flagsByte |= flags->Chest1;
flagsByte |= flags->Chest1; flagsByte |= flags->Chest2 << 1;
flagsByte |= flags->Chest2 << 1; flagsByte |= flags->Chest3 << 2;
flagsByte |= flags->Chest3 << 2; flagsByte |= flags->Chest4 << 3;
flagsByte |= flags->Chest4 << 3; flagsByte |= flags->Quadrant1 << 4;
flagsByte |= flags->Quadrant1 << 4; flagsByte |= flags->Quadrant2 << 5;
flagsByte |= flags->Quadrant2 << 5; flagsByte |= flags->Quadrant3 << 6;
flagsByte |= flags->Quadrant3 << 6; flagsByte |= flags->Quadrant4 << 7;
flagsByte |= flags->Quadrant4 << 7; writeUByte(flagsByte);
writeUByte(flagsByte); flagsByte = 0;
flagsByte = 0; flagsByte |= flags->Door1;
flagsByte |= flags->Door1; flagsByte |= flags->Door2 << 1;
flagsByte |= flags->Door2 << 1; flagsByte |= flags->Door3 << 2;
flagsByte |= flags->Door3 << 2; flagsByte |= flags->Door4 << 3;
flagsByte |= flags->Door4 << 3; flagsByte |= flags->BossBattleWon << 4;
flagsByte |= flags->BossBattleWon << 4; flagsByte |= flags->Key << 5;
flagsByte |= flags->Key << 5; flagsByte |= flags->KeyOrChest << 6;
flagsByte |= flags->KeyOrChest << 6; flagsByte |= flags->ChestOrTile << 7;
flagsByte |= flags->ChestOrTile << 7; writeUByte(flagsByte);
writeUByte(flagsByte);
} }
void ALTTPFileWriter::writeOverworldEvent(ALTTPOverworldEvent* event) void ALTTPFileWriter::writeOverworldEvent(ALTTPOverworldEvent* event) {
{ atUint8 flagsByte = 0;
atUint8 flagsByte = 0; flagsByte |= event->Unused1;
flagsByte |= event->Unused1; flagsByte |= event->HeartPiece << 1;
flagsByte |= event->HeartPiece << 1; flagsByte |= event->Overlay << 2;
flagsByte |= event->Overlay << 2; flagsByte |= event->Unused2 << 3;
flagsByte |= event->Unused2 << 3; flagsByte |= event->Unused3 << 4;
flagsByte |= event->Unused3 << 4; flagsByte |= event->Unused4 << 5;
flagsByte |= event->Unused4 << 5; flagsByte |= event->Set << 6;
flagsByte |= event->Set << 6; flagsByte |= event->Unused5 << 7;
flagsByte |= event->Unused5 << 7; writeUByte(flagsByte);
writeUByte(flagsByte);
} }
void ALTTPFileWriter::writeDungeonItems(ALTTPDungeonItemFlags flags) void ALTTPFileWriter::writeDungeonItems(ALTTPDungeonItemFlags flags) {
{ atUint8 flagsByte = 0;
atUint8 flagsByte = 0; flagsByte |= flags.Unused1;
flagsByte |= flags.Unused1; flagsByte |= flags.Unused2 << 1;
flagsByte |= flags.Unused2 << 1; flagsByte |= flags.GanonsTower << 2;
flagsByte |= flags.GanonsTower << 2; flagsByte |= flags.TurtleRock << 3;
flagsByte |= flags.TurtleRock << 3; flagsByte |= flags.TowerOfHera << 4;
flagsByte |= flags.TowerOfHera << 4; flagsByte |= flags.IcePalace << 5;
flagsByte |= flags.IcePalace << 5; flagsByte |= flags.SkullWoods << 6;
flagsByte |= flags.SkullWoods << 6; flagsByte |= flags.MiseryMire << 7;
flagsByte |= flags.MiseryMire << 7; writeUByte(flagsByte);
writeUByte(flagsByte); flagsByte = 0;
flagsByte = 0; flagsByte |= flags.DarkPalace;
flagsByte |= flags.DarkPalace; flagsByte |= flags.SwampPalace << 1;
flagsByte |= flags.SwampPalace << 1; flagsByte |= flags.HyruleCastle2 << 2;
flagsByte |= flags.HyruleCastle2 << 2; flagsByte |= flags.DesertPalace << 3;
flagsByte |= flags.DesertPalace << 3; flagsByte |= flags.EasternPalace << 4;
flagsByte |= flags.EasternPalace << 4; flagsByte |= flags.HyruleCastle << 5;
flagsByte |= flags.HyruleCastle << 5; flagsByte |= flags.SewerPassage << 6;
flagsByte |= flags.SewerPassage << 6; writeUByte(flagsByte);
writeUByte(flagsByte);
} }
atUint16 ALTTPFileWriter::calculateChecksum(atUint32 game) atUint16 ALTTPFileWriter::calculateChecksum(atUint32 game) {
{ /*
/* * ALTTP's checksum is very basic
* ALTTP's checksum is very basic * It adds each word up and then subtracts the sum from 0x5a5a
* It adds each word up and then subtracts the sum from 0x5a5a * The number seems pretty arbitrary, but it enables the game to differentiate
* The number seems pretty arbitrary, but it enables the game to differentiate * it from a number that just happens to equal the sum outright, preventing "false positives."
* it from a number that just happens to equal the sum outright, preventing "false positives." *
* * Ignoring the algorithm for figuring out it's position in the buffer the equation is basically:
* Ignoring the algorithm for figuring out it's position in the buffer the equation is basically: * s = s + w
* s = s + w * s = (0x5a5a - s);
* s = (0x5a5a - s); * s == sum
* s == sum * w == current word
* w == current word *
* * For those who don't know a word is a two byte pair, i.e 0xFF and 0xFE constitutes a word.
* For those who don't know a word is a two byte pair, i.e 0xFF and 0xFE constitutes a word. */
*/
// First we start at 0 // First we start at 0
atUint16 sum = 0; atUint16 sum = 0;
for (atUint32 i = 0; i < 0x4FE; i += 2) for (atUint32 i = 0; i < 0x4FE; i += 2)
// Add each word one by one // Add each word one by one
sum += *(atUint16*)(m_data + (i + (0x500 * game))); sum += *(atUint16*)(m_data + (i + (0x500 * game)));
// Subtract it from 0x5a5a to get our true checksum // Subtract it from 0x5a5a to get our true checksum
return (0x5a5a - sum); return (0x5a5a - sum);
/* /*
* There is one caveat to this algorithm however, * There is one caveat to this algorithm however,
* It makes it difficult to manually edit this in a hex editor since it's not a common * It makes it difficult to manually edit this in a hex editor since it's not a common
* algorithm and most hexeditor with built in checksum calculators won't have it, however it's * algorithm and most hexeditor with built in checksum calculators won't have it, however it's
* it's extremely basic, making it a non-issue really. * it's extremely basic, making it a non-issue really.
*/ */
} }
} // io } // namespace io
} // zelda } // namespace athena

File diff suppressed because it is too large Load Diff

View File

@ -3,232 +3,182 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
namespace athena::checksums namespace athena::checksums {
{ atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed, atUint64 final) {
atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed, atUint64 final) static const atUint64 crc64Table[256] = {
{ 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, 0x493366450E42ECDF,
static const atUint64 crc64Table[256] = 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A, 0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D,
{ 0x17870F5D4F51B498, 0x5577EEB6E6BB820B, 0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847,
0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, 0x1C4488F3E8F96ED4, 0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A,
0x493366450E42ECDF, 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A, 0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285, 0xF45BB4758C645C51,
0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4, 0xBD68D2308226B08E, 0xFF9833DB2BCC861D,
0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, 0x1C4488F3E8F96ED4, 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B, 0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8,
0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A, 0x0B6BD3C3DBFD506B, 0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4,
0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285, 0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5, 0x172F5B3033043EBF,
0xF45BB4758C645C51, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4, 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A, 0xAA478900B1228E31, 0xE8B768EB18C8B8A2,
0xBD68D2308226B08E, 0xFF9833DB2BCC861D, 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B, 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584, 0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8,
0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, 0x0B6BD3C3DBFD506B, 0x2465CD79455E395B, 0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A,
0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4, 0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5, 0xDA050215EA6C212F,
0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5, 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A, 0x93366450E42ECDF0, 0xD1C685BB4DC4FB63,
0x172F5B3033043EBF, 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A, 0x16D7A787B7FAA0D6, 0x5427466C1E109645, 0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7,
0xAA478900B1228E31, 0xE8B768EB18C8B8A2, 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584, 0x8F72ECA30CD7A324, 0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB,
0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8, 0x2465CD79455E395B, 0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75, 0xF50B1CAF74CF481F,
0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA, 0x2E5EB66066087D7E, 0x6CAE578BCFE24BED,
0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5, 0xABBF75B735DC1058, 0xE94F945C9C3626CB, 0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87,
0xDA050215EA6C212F, 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A, 0xA07CF2199274CA14, 0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144,
0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, 0x16D7A787B7FAA0D6, 0x5427466C1E109645, 0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B, 0x84193F60D72AF34F,
0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, 0x8F72ECA30CD7A324, 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA, 0xCD2A5925D9681F90, 0x8FDAB8CE70822903,
0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB, 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425, 0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238,
0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75, 0xB753A929A170F4AB, 0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874,
0xF50B1CAF74CF481F, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA, 0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15, 0xAB1721DA49899A7F,
0x2E5EB66066087D7E, 0x6CAE578BCFE24BED, 0xABBF75B735DC1058, 0xE94F945C9C3626CB, 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA, 0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E,
0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, 0xA07CF2199274CA14, 0x731B26172EE619EB, 0x31EBC7FC870C2F78, 0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534,
0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144, 0x78D8A1B9894EC3A7, 0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6,
0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B, 0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19, 0x90C79D3FEDD3F122,
0x84193F60D72AF34F, 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA, 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97, 0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E,
0xCD2A5925D9681F90, 0x8FDAB8CE70822903, 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425, 0x5C1538ADB04570DB, 0x1EE5D94619AF4648, 0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA,
0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238, 0xB753A929A170F4AB, 0xC5B073890B687329, 0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6,
0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874, 0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6, 0x73B3727A52B393CC,
0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15, 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879, 0xA8E6D8B54074A6AD, 0xEA16395EE99E903E,
0xAB1721DA49899A7F, 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA, 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18, 0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754,
0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, 0x731B26172EE619EB, 0x31EBC7FC870C2F78, 0x26C49CCCB40811C7, 0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149,
0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, 0x78D8A1B9894EC3A7, 0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96, 0xCEDBA04AD0952342,
0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6, 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7, 0x87E8C60FDED7CF9D, 0xC51827E4773DF90E,
0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19, 0x020905D88D03A2BB, 0x40F9E43324E99428, 0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4,
0x90C79D3FEDD3F122, 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97, 0xEBEEC5E96D600E57, 0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288,
0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E, 0x5C1538ADB04570DB, 0x1EE5D94619AF4648, 0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9, 0xF7AA4D1A85996083,
0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, 0xC5B073890B687329, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36, 0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E,
0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6, 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8, 0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4,
0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6, 0xC4E0DB53F3C36767, 0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206,
0x73B3727A52B393CC, 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879, 0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9, 0xE085162AB69D5E3C,
0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18, 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589, 0xA9B6706FB8DFB2E3, 0xEB46918411358470,
0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754, 0x26C49CCCB40811C7, 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956, 0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4,
0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149, 0xB5F2F89C5026DC37, 0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8,
0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96, 0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066, 0xCF8B0890283E370C,
0xCEDBA04AD0952342, 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7, 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9, 0x14DEA25F3AF9026D, 0x562E43B4931334FE,
0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, 0x020905D88D03A2BB, 0x40F9E43324E99428, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8, 0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394,
0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, 0xEBEEC5E96D600E57, 0x9AFCE626CE85B507,
0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288, };
0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9,
0xF7AA4D1A85996083, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36,
0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E, 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8,
0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, 0xC4E0DB53F3C36767,
0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206,
0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9,
0xE085162AB69D5E3C, 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589,
0xA9B6706FB8DFB2E3, 0xEB46918411358470, 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956,
0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4, 0xB5F2F89C5026DC37,
0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8,
0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066,
0xCF8B0890283E370C, 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9,
0x14DEA25F3AF9026D, 0x562E43B4931334FE, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8,
0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, 0x9AFCE626CE85B507,
};
if (!data) if (!data)
return seed; return seed;
atUint64 checksum = seed; atUint64 checksum = seed;
int pos = 0; int pos = 0;
while (length--) while (length--)
checksum = crc64Table[((checksum >> 56) ^ data[pos++]) & 0xff] ^ (checksum << 8); checksum = crc64Table[((checksum >> 56) ^ data[pos++]) & 0xff] ^ (checksum << 8);
return checksum ^ final; return checksum ^ final;
} }
atUint32 crc32(const atUint8* data, atUint64 length, atUint32 seed, atUint32 final) atUint32 crc32(const atUint8* data, atUint64 length, atUint32 seed, atUint32 final) {
{ static const atUint32 crc32Table[256] = {
static const atUint32 crc32Table[256] = 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832,
{ 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
if (!data) if (!data)
return seed; return seed;
atUint32 checksum = seed; atUint32 checksum = seed;
int pos = 0; int pos = 0;
while (length--) while (length--)
checksum = (checksum >> 8) ^ crc32Table[(checksum & 0xFF) ^ data[pos++]]; checksum = (checksum >> 8) ^ crc32Table[(checksum & 0xFF) ^ data[pos++]];
return checksum ^ final; return checksum ^ final;
} }
atUint16 crc16CCITT(const atUint8* data, atUint64 length, atUint16 seed, atUint16 final) atUint16 crc16CCITT(const atUint8* data, atUint64 length, atUint16 seed, atUint16 final) {
{ static const atUint16 crc16CCITTTable[256] = {
static const atUint16 crc16CCITTTable [256] = 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad,
{ 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a,
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b,
0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861,
0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96,
0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87,
0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a,
0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290,
0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e,
0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f,
0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c,
0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83,
0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb,
0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0,
0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,
0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657,
0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9,
0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882,
0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e,
0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07,
0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d,
0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
atUint16 checksum = seed; atUint16 checksum = seed;
int pos = 0; int pos = 0;
while (length--) while (length--)
checksum = crc16CCITTTable[(data[pos++] ^ (checksum >> 8)) & 0xFF] ^ (checksum << 8); checksum = crc16CCITTTable[(data[pos++] ^ (checksum >> 8)) & 0xFF] ^ (checksum << 8);
return checksum ^ final; return checksum ^ final;
} }
atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed, atUint64 final) atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed, atUint64 final) {
{ if (data)
if (data) return seed;
return seed;
static const atUint16 crc16Table[256] = static const atUint16 crc16Table[256] = {
{ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1,
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x4100, 0x81C1, 0x8081, 0x4040};
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
atInt32 pos = 0; atInt32 pos = 0;
atUint16 checksum = seed; atUint16 checksum = seed;
while (length--) while (length--)
checksum = (crc16Table[(checksum ^ data[pos++]) & 0xFF] ^ (checksum >> 8)); checksum = (crc16Table[(checksum ^ data[pos++]) & 0xFF] ^ (checksum >> 8));
return checksum ^ final; return checksum ^ final;
} }
} // Checksums } // namespace athena::checksums

View File

@ -5,351 +5,311 @@
#include "LZ77/LZType10.hpp" #include "LZ77/LZType10.hpp"
#include "LZ77/LZType11.hpp" #include "LZ77/LZType11.hpp"
namespace athena::io::Compression namespace athena::io::Compression {
{
atInt32 decompressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen) atInt32 decompressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen) {
{ z_stream strm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
z_stream strm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; strm.total_in = strm.avail_in = srcLen;
strm.total_in = strm.avail_in = srcLen; strm.total_out = strm.avail_out = dstLen;
strm.total_out = strm.avail_out = dstLen; strm.next_in = (Bytef*)src;
strm.next_in = (Bytef*) src; strm.next_out = (Bytef*)dst;
strm.next_out = (Bytef*) dst;
strm.zalloc = Z_NULL; strm.zalloc = Z_NULL;
strm.zfree = Z_NULL; strm.zfree = Z_NULL;
strm.opaque = Z_NULL; strm.opaque = Z_NULL;
atInt32 err = -1; atInt32 err = -1;
atInt32 ret = -1; atInt32 ret = -1;
err = inflateInit(&strm); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib err = inflateInit(&strm); // 15 window bits, and the +32 tells zlib to to detect if using gzip or zlib
if (err == Z_OK) if (err == Z_OK) {
{ err = inflate(&strm, Z_FINISH);
err = inflate(&strm, Z_FINISH);
if (err == Z_STREAM_END) if (err == Z_STREAM_END)
ret = strm.total_out; ret = strm.total_out;
else else {
{ inflateEnd(&strm);
inflateEnd(&strm); return err;
return err;
}
} }
else } else {
{
inflateEnd(&strm);
return err;
}
inflateEnd(&strm); inflateEnd(&strm);
return err;
}
return ret; inflateEnd(&strm);
return ret;
} }
atInt32 compressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen) atInt32 compressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen) {
{ z_stream strm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
z_stream strm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; strm.total_in = strm.avail_in = srcLen;
strm.total_in = strm.avail_in = srcLen; strm.total_out = strm.avail_out = dstLen;
strm.total_out = strm.avail_out = dstLen; strm.next_in = (Bytef*)src;
strm.next_in = (Bytef*) src; strm.next_out = (Bytef*)dst;
strm.next_out = (Bytef*) dst;
strm.zalloc = Z_NULL; strm.zalloc = Z_NULL;
strm.zfree = Z_NULL; strm.zfree = Z_NULL;
strm.opaque = Z_NULL; strm.opaque = Z_NULL;
atInt32 err = -1; atInt32 err = -1;
atInt32 ret = -1; atInt32 ret = -1;
err = deflateInit(&strm, Z_BEST_COMPRESSION); err = deflateInit(&strm, Z_BEST_COMPRESSION);
if (err == Z_OK) if (err == Z_OK) {
{ err = deflate(&strm, Z_FINISH);
err = deflate(&strm, Z_FINISH);
if (err == Z_STREAM_END) if (err == Z_STREAM_END)
ret = strm.total_out; ret = strm.total_out;
else else {
{ deflateEnd(&strm);
deflateEnd(&strm); return err;
return err;
}
} }
else } else {
{
deflateEnd(&strm);
return err;
}
deflateEnd(&strm); deflateEnd(&strm);
return err;
}
return ret; deflateEnd(&strm);
return ret;
} }
atInt32 decompressLZO(const atUint8* source, const atInt32 sourceSize, atUint8* dst, atInt32& dstSize) atInt32 decompressLZO(const atUint8* source, const atInt32 sourceSize, atUint8* dst, atInt32& dstSize) {
{ int srcSize = sourceSize;
int srcSize = sourceSize; lzo_uint size = dstSize;
lzo_uint size = dstSize; int result = lzo1x_decompress_safe(source, srcSize, dst, &size, NULL);
int result = lzo1x_decompress_safe(source, srcSize, dst, &size, NULL); dstSize -= (atInt32)size;
dstSize -= (atInt32)size;
return result; return result;
} }
//src points to the yaz0 source data (to the "real" source data, not at the header!) // src points to the yaz0 source data (to the "real" source data, not at the header!)
//dst points to a buffer uncompressedSize bytes large (you get uncompressedSize from // dst points to a buffer uncompressedSize bytes large (you get uncompressedSize from
//the second 4 bytes in the Yaz0 header). // the second 4 bytes in the Yaz0 header).
atUint32 yaz0Decode(const atUint8* src, atUint8* dst, atUint32 uncompressedSize) atUint32 yaz0Decode(const atUint8* src, atUint8* dst, atUint32 uncompressedSize) {
{ atUint32 srcPlace = 0, dstPlace = 0; // current read/write positions
atUint32 srcPlace = 0, dstPlace = 0; //current read/write positions
atInt32 validBitCount = 0; //number of valid bits left in "code" byte atInt32 validBitCount = 0; // number of valid bits left in "code" byte
atUint8 currCodeByte; atUint8 currCodeByte;
while (dstPlace < uncompressedSize) while (dstPlace < uncompressedSize) {
{ // read new "code" byte if the current one is used up
//read new "code" byte if the current one is used up if (validBitCount == 0) {
if (validBitCount == 0) currCodeByte = src[srcPlace];
{ ++srcPlace;
currCodeByte = src[srcPlace]; validBitCount = 8;
++srcPlace;
validBitCount = 8;
}
if ((currCodeByte & 0x80) != 0)
{
//straight copy
dst[dstPlace] = src[srcPlace];
dstPlace++;
srcPlace++;
}
else
{
//RLE part
atUint8 byte1 = src[srcPlace];
atUint8 byte2 = src[srcPlace + 1];
srcPlace += 2;
atUint32 dist = ((byte1 & 0xF) << 8) | byte2;
atUint32 copySource = dstPlace - (dist + 1);
atUint32 numBytes = byte1 >> 4;
if (numBytes == 0)
{
numBytes = src[srcPlace] + 0x12;
srcPlace++;
}
else
numBytes += 2;
//copy run
for (atUint32 i = 0; i < numBytes; ++i)
{
dst[dstPlace] = dst[copySource];
copySource++;
dstPlace++;
}
}
//use next bit from "code" byte
currCodeByte <<= 1;
validBitCount -= 1;
} }
return dstPlace; if ((currCodeByte & 0x80) != 0) {
// straight copy
dst[dstPlace] = src[srcPlace];
dstPlace++;
srcPlace++;
} else {
// RLE part
atUint8 byte1 = src[srcPlace];
atUint8 byte2 = src[srcPlace + 1];
srcPlace += 2;
atUint32 dist = ((byte1 & 0xF) << 8) | byte2;
atUint32 copySource = dstPlace - (dist + 1);
atUint32 numBytes = byte1 >> 4;
if (numBytes == 0) {
numBytes = src[srcPlace] + 0x12;
srcPlace++;
} else
numBytes += 2;
// copy run
for (atUint32 i = 0; i < numBytes; ++i) {
dst[dstPlace] = dst[copySource];
copySource++;
dstPlace++;
}
}
// use next bit from "code" byte
currCodeByte <<= 1;
validBitCount -= 1;
}
return dstPlace;
} }
// Yaz0 encode // Yaz0 encode
typedef struct typedef struct {
{ atUint32 srcPos, dstPos;
atUint32 srcPos, dstPos;
} yaz0_Ret; } yaz0_Ret;
atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos); atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos);
atUint32 nintendoEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos); atUint32 nintendoEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos);
atUint32 yaz0Encode(const atUint8* src, atUint32 srcSize, atUint8* data) atUint32 yaz0Encode(const atUint8* src, atUint32 srcSize, atUint8* data) {
{ yaz0_Ret r = {0, 0};
yaz0_Ret r = { 0, 0 }; atInt32 pos = 0;
atInt32 pos = 0; atUint8 dst[24]; // 8 codes * 3 bytes maximum
atUint8 dst[24]; // 8 codes * 3 bytes maximum atUint32 dstSize = 0;
atUint32 dstSize = 0; atUint32 i;
atUint32 i;
atUint32 validBitCount = 0; //number of valid bits left in "code" byte atUint32 validBitCount = 0; // number of valid bits left in "code" byte
atUint8 currCodeByte = 0; atUint8 currCodeByte = 0;
while (r.srcPos < srcSize) while (r.srcPos < srcSize) {
{ atUint32 numBytes;
atUint32 numBytes; atUint32 matchPos;
atUint32 matchPos; numBytes = nintendoEnc(src, srcSize, r.srcPos, &matchPos);
numBytes = nintendoEnc(src, srcSize, r.srcPos, &matchPos);
if (numBytes < 3) if (numBytes < 3) {
{ // straight copy
//straight copy dst[r.dstPos] = src[r.srcPos];
dst[r.dstPos] = src[r.srcPos]; r.dstPos++;
r.dstPos++; r.srcPos++;
r.srcPos++; // set flag for straight copy
//set flag for straight copy currCodeByte |= (0x80 >> validBitCount);
currCodeByte |= (0x80 >> validBitCount); } else {
} // RLE part
else atUint32 dist = r.srcPos - matchPos - 1;
{ atUint8 byte1, byte2, byte3;
//RLE part
atUint32 dist = r.srcPos - matchPos - 1;
atUint8 byte1, byte2, byte3;
if (numBytes >= 0x12) // 3 byte encoding if (numBytes >= 0x12) // 3 byte encoding
{ {
byte1 = 0 | (dist >> 8); byte1 = 0 | (dist >> 8);
byte2 = dist & 0xff; byte2 = dist & 0xff;
dst[r.dstPos++] = byte1; dst[r.dstPos++] = byte1;
dst[r.dstPos++] = byte2; dst[r.dstPos++] = byte2;
// maximum runlength for 3 byte encoding // maximum runlength for 3 byte encoding
if (numBytes > 0xff + 0x12) if (numBytes > 0xff + 0x12)
numBytes = 0xff + 0x12; numBytes = 0xff + 0x12;
byte3 = numBytes - 0x12; byte3 = numBytes - 0x12;
dst[r.dstPos++] = byte3; dst[r.dstPos++] = byte3;
} } else // 2 byte encoding
else // 2 byte encoding {
{ byte1 = ((numBytes - 2) << 4) | (dist >> 8);
byte1 = ((numBytes - 2) << 4) | (dist >> 8); byte2 = dist & 0xff;
byte2 = dist & 0xff; dst[r.dstPos++] = byte1;
dst[r.dstPos++] = byte1; dst[r.dstPos++] = byte2;
dst[r.dstPos++] = byte2; }
}
r.srcPos += numBytes; r.srcPos += numBytes;
}
validBitCount++;
//write eight codes
if (validBitCount == 8)
{
data[pos] = currCodeByte;
pos++;
for (i = 0; i </*=*/r.dstPos; pos++, i++)
data[pos] = dst[i];
dstSize += r.dstPos + 1;
currCodeByte = 0;
validBitCount = 0;
r.dstPos = 0;
}
} }
if (validBitCount > 0) validBitCount++;
{
data[pos] = currCodeByte;
pos++;
for (i = 0; i </*=*/r.dstPos; pos++, i++) // write eight codes
data[pos] = dst[i]; if (validBitCount == 8) {
data[pos] = currCodeByte;
pos++;
dstSize += r.dstPos + 1; for (i = 0; i < /*=*/r.dstPos; pos++, i++)
data[pos] = dst[i];
currCodeByte = 0; dstSize += r.dstPos + 1;
validBitCount = 0;
r.dstPos = 0; currCodeByte = 0;
validBitCount = 0;
r.dstPos = 0;
} }
}
return dstSize; if (validBitCount > 0) {
data[pos] = currCodeByte;
pos++;
for (i = 0; i < /*=*/r.dstPos; pos++, i++)
data[pos] = dst[i];
dstSize += r.dstPos + 1;
currCodeByte = 0;
validBitCount = 0;
r.dstPos = 0;
}
return dstSize;
} }
// a lookahead encoding scheme for ngc Yaz0 // a lookahead encoding scheme for ngc Yaz0
atUint32 nintendoEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos) atUint32 nintendoEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos) {
{ atUint32 numBytes = 1;
atUint32 numBytes = 1; static atUint32 numBytes1;
static atUint32 numBytes1; static atUint32 matchPos;
static atUint32 matchPos; static atInt32 prevFlag = 0;
static atInt32 prevFlag = 0;
// if prevFlag is set, it means that the previous position was determined by look-ahead try. // if prevFlag is set, it means that the previous position was determined by look-ahead try.
// so just use it. this is not the best optimization, but nintendo's choice for speed. // so just use it. this is not the best optimization, but nintendo's choice for speed.
if (prevFlag == 1) if (prevFlag == 1) {
{
*pMatchPos = matchPos;
prevFlag = 0;
return numBytes1;
}
prevFlag = 0;
numBytes = simpleEnc(src, size, pos, &matchPos);
*pMatchPos = matchPos; *pMatchPos = matchPos;
prevFlag = 0;
return numBytes1;
}
// if this position is RLE encoded, then compare to copying 1 byte and next position(pos+1) encoding prevFlag = 0;
if (numBytes >= 3) numBytes = simpleEnc(src, size, pos, &matchPos);
{ *pMatchPos = matchPos;
numBytes1 = simpleEnc(src, size, pos + 1, &matchPos);
// if the next position encoding is +2 longer than current position, choose it. // if this position is RLE encoded, then compare to copying 1 byte and next position(pos+1) encoding
// this does not guarantee the best optimization, but fairly good optimization with speed. if (numBytes >= 3) {
if (numBytes1 >= numBytes + 2) numBytes1 = simpleEnc(src, size, pos + 1, &matchPos);
{
numBytes = 1; // if the next position encoding is +2 longer than current position, choose it.
prevFlag = 1; // this does not guarantee the best optimization, but fairly good optimization with speed.
} if (numBytes1 >= numBytes + 2) {
numBytes = 1;
prevFlag = 1;
} }
}
return numBytes; return numBytes;
} }
// simple and straight encoding scheme for Yaz0 // simple and straight encoding scheme for Yaz0
atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos) atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos) {
{ int startPos = pos - 0x1000, j, i;
int startPos = pos - 0x1000, j, i; atUint32 numBytes = 1;
atUint32 numBytes = 1; atUint32 matchPos = 0;
atUint32 matchPos = 0;
if (startPos < 0) if (startPos < 0)
startPos = 0; startPos = 0;
for (i = startPos; i < pos; i++) for (i = startPos; i < pos; i++) {
{ for (j = 0; j < size - pos; j++) {
for (j = 0; j < size - pos; j++) if (src[i + j] != src[j + pos])
{ break;
if (src[i + j] != src[j + pos])
break;
}
if ((atUint32)j > numBytes)
{
numBytes = j;
matchPos = i;
}
} }
*pMatchPos = matchPos; if ((atUint32)j > numBytes) {
numBytes = j;
matchPos = i;
}
}
if (numBytes == 2) *pMatchPos = matchPos;
numBytes = 1;
return numBytes; if (numBytes == 2)
numBytes = 1;
return numBytes;
} }
atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst) atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst) {
{ if (*(atUint8*)src == 0x11)
if (*(atUint8*)src == 0x11) return LZType11().decompress(src, dst, srcLen);
return LZType11().decompress(src, dst, srcLen);
return LZType10(2).decompress(src, dst, srcLen); return LZType10(2).decompress(src, dst, srcLen);
} }
atUint32 compressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst, bool extended) atUint32 compressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst, bool extended) {
{ if (extended)
if (extended) return LZType11().compress(src, dst, srcLen);
return LZType11().compress(src, dst, srcLen);
return LZType10(2).compress(src, dst, srcLen); return LZType10(2).compress(src, dst, srcLen);
} }
} // Compression } // namespace athena::io::Compression

File diff suppressed because it is too large Load Diff

View File

@ -18,89 +18,70 @@
#define realpath(__name, __resolved) _fullpath((__name), (__resolved), 4096) #define realpath(__name, __resolved) _fullpath((__name), (__resolved), 4096)
#endif #endif
namespace athena namespace athena {
{ Dir::Dir(std::string_view path) : m_path(path) {}
Dir::Dir(std::string_view path)
: m_path(path)
{
}
std::string Dir::absolutePath() const std::string Dir::absolutePath() const { return FileInfo(m_path).absoluteFilePath(); }
{
return FileInfo(m_path).absoluteFilePath();
}
bool Dir::isDir() const
{
atStat64_t st;
int e = atStat64(m_path.c_str(), &st);
if (e < 0)
return false;
return (S_ISDIR(st.st_mode));
}
bool Dir::cd(std::string_view path)
{
Dir tmp(path);
if (tmp.isDir())
{
m_path = path;
return true;
}
bool Dir::isDir() const {
atStat64_t st;
int e = atStat64(m_path.c_str(), &st);
if (e < 0)
return false; return false;
return (S_ISDIR(st.st_mode));
} }
bool Dir::rm(std::string_view path) bool Dir::cd(std::string_view path) {
{ Dir tmp(path);
return !(remove((m_path + "/" + path.data()).c_str()) < 0); if (tmp.isDir()) {
m_path = path;
return true;
}
return false;
} }
bool Dir::touch() bool Dir::rm(std::string_view path) { return !(remove((m_path + "/" + path.data()).c_str()) < 0); }
{
srand(time(NULL)); bool Dir::touch() {
atUint64 tmp = utility::rand64(); srand(time(NULL));
std::string tmpFile = utility::sprintf("%" PRIX64 ".tmp", tmp); atUint64 tmp = utility::rand64();
bool ret = FileInfo(m_path + "/" + tmpFile).touch(); std::string tmpFile = utility::sprintf("%" PRIX64 ".tmp", tmp);
if (ret) bool ret = FileInfo(m_path + "/" + tmpFile).touch();
return rm(tmpFile); if (ret)
return false; return rm(tmpFile);
return false;
} }
bool Dir::mkdir(std::string_view dir, mode_t mode) bool Dir::mkdir(std::string_view dir, mode_t mode) {
{
#if _WIN32 #if _WIN32
return !(::_mkdir(dir.data()) < 0); return !(::_mkdir(dir.data()) < 0);
#else #else
return !(::mkdir(dir.data(), mode) < 0); return !(::mkdir(dir.data(), mode) < 0);
#endif #endif
} }
bool Dir::mkpath(std::string_view path, mode_t mode) bool Dir::mkpath(std::string_view path, mode_t mode) {
{ std::vector<std::string> dirs = utility::split(path, '/');
std::vector<std::string> dirs = utility::split(path, '/'); if (dirs.empty())
if (dirs.empty()) dirs = utility::split(path, '\\');
dirs = utility::split(path, '\\'); if (dirs.empty())
if (dirs.empty()) return false;
return false;
bool ret = false; bool ret = false;
std::string newPath; std::string newPath;
for (const std::string& dir : dirs) for (const std::string& dir : dirs) {
{ if (dir.size() == 2 && dir[1] == ':') {
if (dir.size() == 2 && dir[1] == ':') newPath += dir + "//";
{ continue;
newPath += dir + "//";
continue;
}
newPath += "/" + dir;
ret = mkdir(newPath, mode);
} }
newPath += "/" + dir;
ret = mkdir(newPath, mode);
}
// we only care if the last directory was created // we only care if the last directory was created
return ret; return ret;
}
} }
} // namespace athena

View File

@ -29,168 +29,149 @@
#define realpath(__name, __resolved) _fullpath((__resolved), (__name), 4096) #define realpath(__name, __resolved) _fullpath((__resolved), (__name), 4096)
#endif #endif
namespace athena namespace athena {
{
FileInfo::FileInfo(std::string_view path) FileInfo::FileInfo(std::string_view path) : m_path(path) {}
: m_path(path)
{ std::string FileInfo::absolutePath() const {
std::string path = absoluteFilePath();
size_t pos = path.find_last_of('/');
if (pos == std::string::npos)
pos = path.find_last_of('\\');
if (pos == std::string::npos)
return path;
return path.substr(0, pos + 1);
} }
std::string FileInfo::absolutePath() const std::string FileInfo::absoluteFilePath() const {
{ char ret[4096];
std::string path = absoluteFilePath(); realpath(m_path.c_str(), ret);
size_t pos = path.find_last_of('/'); return ret;
if (pos == std::string::npos)
pos = path.find_last_of('\\');
if (pos == std::string::npos)
return path;
return path.substr(0, pos+1);
} }
std::string FileInfo::absoluteFilePath() const std::string FileInfo::filename() const {
{ size_t pos = m_path.find_last_of('/');
char ret[4096]; if (pos == std::string::npos)
realpath(m_path.c_str(), ret); pos = m_path.find_last_of('\\');
return ret; if (pos == std::string::npos)
return m_path;
return m_path.substr(pos + 1);
} }
std::string FileInfo::filename() const std::string FileInfo::extension() const {
{ size_t pos = m_path.find_last_of('.');
size_t pos = m_path.find_last_of('/'); if (pos == std::string::npos)
if (pos == std::string::npos) return std::string();
pos = m_path.find_last_of('\\');
if (pos == std::string::npos) return m_path.substr(pos + 1);
return m_path;
return m_path.substr(pos + 1);
} }
std::string FileInfo::extension() const atUint64 FileInfo::size() const { return utility::fileSize(m_path); }
{
size_t pos = m_path.find_last_of('.');
if (pos == std::string::npos)
return std::string();
return m_path.substr(pos + 1); bool FileInfo::exists() const {
atStat64_t st;
int e = atStat64(m_path.c_str(), &st);
if (e < 0)
return false;
return (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode));
} }
atUint64 FileInfo::size() const bool FileInfo::isLink() const {
{ atStat64_t st;
return utility::fileSize(m_path); int e = atStat64(m_path.c_str(), &st);
if (e < 0)
return false;
return (S_ISLNK(st.st_mode));
} }
bool FileInfo::exists() const bool FileInfo::isFile() const {
{ atStat64_t st;
atStat64_t st; int e = atStat64(m_path.c_str(), &st);
int e = atStat64(m_path.c_str(), &st); if (e < 0)
return false;
if (e < 0) return (S_ISREG(st.st_mode));
return false;
return (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode));
} }
bool FileInfo::isLink() const bool FileInfo::touch() const {
{
atStat64_t st;
int e = atStat64(m_path.c_str(), &st);
if (e < 0)
return false;
return (S_ISLNK(st.st_mode));
}
bool FileInfo::isFile() const
{
atStat64_t st;
int e = atStat64(m_path.c_str(), &st);
if (e < 0)
return false;
return (S_ISREG(st.st_mode));
}
bool FileInfo::touch() const
{
#if defined(__GNUC__) && !(defined(HW_DOL) || defined(HW_RVL) || defined(GEKKO)) #if defined(__GNUC__) && !(defined(HW_DOL) || defined(HW_RVL) || defined(GEKKO))
atStat64_t st; atStat64_t st;
if (atStat64(m_path.c_str(), &st) < 0) { if (atStat64(m_path.c_str(), &st) < 0) {
(void)athena::io::FileWriter(m_path); (void)athena::io::FileWriter(m_path);
return true; return true;
} }
if (utimes(m_path.c_str(), NULL) < 0) { if (utimes(m_path.c_str(), NULL) < 0) {
return false; return false;
} }
#elif defined(_WIN32) #elif defined(_WIN32)
FILETIME modtime; FILETIME modtime;
SYSTEMTIME st; SYSTEMTIME st;
HANDLE fh; HANDLE fh;
wchar_t date[80], time[80]; wchar_t date[80], time[80];
#if !WINDOWS_STORE #if !WINDOWS_STORE
fh = CreateFileA(m_path.c_str(), GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, NULL, CREATE_NEW, 0, NULL); fh = CreateFileA(m_path.c_str(), GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, NULL, CREATE_NEW, 0, NULL);
if (fh == INVALID_HANDLE_VALUE) if (fh == INVALID_HANDLE_VALUE)
return false; return false;
/*
* Use GetFileTime() to get the file modification time.
*/
if (GetFileTime(fh, NULL, NULL, &modtime) == 0)
{
CloseHandle(fh);
return false;
}
FileTimeToSystemTime(&modtime, &st);
if (GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, date, sizeof date / sizeof date[0]) == 0 ||
GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, time, sizeof time / sizeof time[0]) == 0)
{
CloseHandle(fh);
return false;
}
/*
* Use SetFileTime() to change the file modification time
* to the current time.
*/
GetSystemTime(&st);
if (GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, date, sizeof date / sizeof date[0]) == 0 ||
GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, time, sizeof time / sizeof time[0]) == 0)
{
CloseHandle(fh);
return false;
}
SystemTimeToFileTime(&st, &modtime);
if (SetFileTime(fh, NULL, NULL, &modtime) == 0)
{
CloseHandle(fh);
return false;
}
/*
* Use GetFileTime() to get the file modification time.
*/
if (GetFileTime(fh, NULL, NULL, &modtime) == 0) {
CloseHandle(fh); CloseHandle(fh);
return false;
}
FileTimeToSystemTime(&modtime, &st);
if (GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, date, sizeof date / sizeof date[0]) == 0 ||
GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, time, sizeof time / sizeof time[0]) == 0) {
CloseHandle(fh);
return false;
}
/*
* Use SetFileTime() to change the file modification time
* to the current time.
*/
GetSystemTime(&st);
if (GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, date, sizeof date / sizeof date[0]) == 0 ||
GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, time, sizeof time / sizeof time[0]) == 0) {
CloseHandle(fh);
return false;
}
SystemTimeToFileTime(&st, &modtime);
if (SetFileTime(fh, NULL, NULL, &modtime) == 0) {
CloseHandle(fh);
return false;
}
CloseHandle(fh);
#endif #endif
#elif (defined(HW_RVL) || defined(HW_DOL)) && defined(GEKKO) #elif (defined(HW_RVL) || defined(HW_DOL)) && defined(GEKKO)
// Generic portable version, not extremely reliable but does work // Generic portable version, not extremely reliable but does work
atUint64 val = 0xCDCDCDCDCD; atUint64 val = 0xCDCDCDCDCD;
{ {
athena::io::FileReader reader(m_path.c_str()); athena::io::FileReader reader(m_path.c_str());
if (reader.isOpen()) if (reader.isOpen())
val = reader.readUint64(); val = reader.readUint64();
} }
{ {
athena::io::FileWriter writer(m_path, false); athena::io::FileWriter writer(m_path, false);
if (val != 0xCDCDCDCDCD && writer.isOpen()) if (val != 0xCDCDCDCDCD && writer.isOpen())
writer.writeUint64(val); writer.writeUint64(val);
else if (!writer.isOpen()) else if (!writer.isOpen())
return false; return false;
} }
#endif #endif
return true; return true;
} }
} } // namespace athena

View File

@ -7,201 +7,170 @@
#include "osx_largefilewrapper.h" #include "osx_largefilewrapper.h"
#endif #endif
namespace athena::io namespace athena::io {
{
FileReader::FileReader(std::string_view filename, atInt32 cacheSize, bool globalErr) FileReader::FileReader(std::string_view filename, atInt32 cacheSize, bool globalErr)
: m_fileHandle(nullptr), : m_fileHandle(nullptr), m_cacheData(nullptr), m_offset(0), m_globalErr(globalErr) {
m_cacheData(nullptr), m_filename = filename;
m_offset(0), open();
m_globalErr(globalErr) setCacheSize(cacheSize);
{
m_filename = filename;
open();
setCacheSize(cacheSize);
} }
FileReader::FileReader(std::wstring_view filename, atInt32 cacheSize, bool globalErr) FileReader::FileReader(std::wstring_view filename, atInt32 cacheSize, bool globalErr)
: m_fileHandle(nullptr), : m_fileHandle(nullptr), m_cacheData(nullptr), m_offset(0), m_globalErr(globalErr) {
m_cacheData(nullptr), m_filename = utility::wideToUtf8(filename);
m_offset(0), open();
m_globalErr(globalErr) setCacheSize(cacheSize);
{
m_filename = utility::wideToUtf8(filename);
open();
setCacheSize(cacheSize);
} }
FileReader::~FileReader() FileReader::~FileReader() {
{ if (isOpen())
if (isOpen()) close();
close();
} }
void FileReader::open() void FileReader::open() {
{ m_fileHandle = fopen(m_filename.c_str(), "rb");
m_fileHandle = fopen(m_filename.c_str(), "rb");
if (!m_fileHandle) if (!m_fileHandle) {
{ std::string _filename = filename();
std::string _filename = filename(); if (m_globalErr)
if (m_globalErr) atError("File not found '%s'", _filename.c_str());
atError("File not found '%s'", _filename.c_str()); setError();
setError();
return;
}
// reset error
m_hasError = false;
}
void FileReader::close()
{
if (!m_fileHandle)
{
if (m_globalErr)
atError("Cannot close an unopened stream");
setError();
return;
}
fclose(m_fileHandle);
m_fileHandle = NULL;
return; return;
}
// reset error
m_hasError = false;
} }
void FileReader::seek(atInt64 pos, SeekOrigin origin) void FileReader::close() {
{ if (!m_fileHandle) {
if (!isOpen()) if (m_globalErr)
return; atError("Cannot close an unopened stream");
setError();
return;
}
// check block position fclose(m_fileHandle);
if (m_blockSize > 0) m_fileHandle = NULL;
{ return;
atUint64 oldOff = m_offset;
switch(origin)
{
case SeekOrigin::Begin:
m_offset = pos;
break;
case SeekOrigin::Current:
m_offset += pos;
break;
case SeekOrigin::End:
m_offset = length() - pos;
break;
}
if (m_offset > length())
{
oldOff = m_offset;
if (m_globalErr)
atError("Unable to seek in file");
setError();
return;
}
size_t block = m_offset / m_blockSize;
if (block != m_curBlock)
{
fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET);
fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle);
m_curBlock = (atInt32)block;
}
}
else if (fseeko64(m_fileHandle, pos, (int)origin) != 0)
{
if (m_globalErr)
atError("Unable to seek in file");
setError();
}
} }
atUint64 FileReader::position() const void FileReader::seek(atInt64 pos, SeekOrigin origin) {
{ if (!isOpen())
if (!isOpen()) return;
{
if (m_globalErr) // check block position
atError("File not open"); if (m_blockSize > 0) {
return 0; atUint64 oldOff = m_offset;
switch (origin) {
case SeekOrigin::Begin:
m_offset = pos;
break;
case SeekOrigin::Current:
m_offset += pos;
break;
case SeekOrigin::End:
m_offset = length() - pos;
break;
}
if (m_offset > length()) {
oldOff = m_offset;
if (m_globalErr)
atError("Unable to seek in file");
setError();
return;
} }
if (m_blockSize > 0) size_t block = m_offset / m_blockSize;
return m_offset; if (block != m_curBlock) {
else fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET);
return ftello64(m_fileHandle); fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle);
} m_curBlock = (atInt32)block;
atUint64 FileReader::length() const
{
if (!isOpen())
{
if (m_globalErr)
atError("File not open");
return 0;
} }
} else if (fseeko64(m_fileHandle, pos, (int)origin) != 0) {
return utility::fileSize(m_filename); if (m_globalErr)
atError("Unable to seek in file");
setError();
}
} }
atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) atUint64 FileReader::position() const {
{ if (!isOpen()) {
if (!isOpen()) if (m_globalErr)
{ atError("File not open");
if (m_globalErr) return 0;
atError("File not open for reading"); }
setError();
return 0; if (m_blockSize > 0)
} return m_offset;
else
if (m_blockSize <= 0) return ftello64(m_fileHandle);
return fread(buf, 1, len, m_fileHandle); }
else
{ atUint64 FileReader::length() const {
atUint64 fs = utility::fileSize(m_filename); if (!isOpen()) {
if (m_offset >= fs) if (m_globalErr)
return 0; atError("File not open");
if (m_offset + len >= fs) return 0;
len = fs - m_offset; }
size_t block = m_offset / m_blockSize; return utility::fileSize(m_filename);
atUint64 cacheOffset = m_offset % m_blockSize; }
atUint64 cacheSize;
atUint64 rem = len; atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) {
atUint8* dst = (atUint8*)buf; if (!isOpen()) {
if (m_globalErr)
while (rem) atError("File not open for reading");
{ setError();
if (block != m_curBlock) return 0;
{ }
fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET);
fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle); if (m_blockSize <= 0)
m_curBlock = (atInt32)block; return fread(buf, 1, len, m_fileHandle);
} else {
atUint64 fs = utility::fileSize(m_filename);
cacheSize = rem; if (m_offset >= fs)
if (cacheSize + cacheOffset > m_blockSize) return 0;
cacheSize = m_blockSize - cacheOffset; if (m_offset + len >= fs)
len = fs - m_offset;
memmove(dst, m_cacheData.get() + cacheOffset, cacheSize);
dst += cacheSize; size_t block = m_offset / m_blockSize;
rem -= cacheSize; atUint64 cacheOffset = m_offset % m_blockSize;
cacheOffset = 0; atUint64 cacheSize;
++block; atUint64 rem = len;
} atUint8* dst = (atUint8*)buf;
m_offset += len;
return dst - (atUint8*)buf; while (rem) {
if (block != m_curBlock) {
fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET);
fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle);
m_curBlock = (atInt32)block;
}
cacheSize = rem;
if (cacheSize + cacheOffset > m_blockSize)
cacheSize = m_blockSize - cacheOffset;
memmove(dst, m_cacheData.get() + cacheOffset, cacheSize);
dst += cacheSize;
rem -= cacheSize;
cacheOffset = 0;
++block;
} }
m_offset += len;
return dst - (atUint8*)buf;
}
} }
void FileReader::setCacheSize(const atInt32 blockSize) void FileReader::setCacheSize(const atInt32 blockSize) {
{ m_blockSize = blockSize;
m_blockSize = blockSize;
if (m_blockSize > length()) if (m_blockSize > length())
m_blockSize = (atInt32)length(); m_blockSize = (atInt32)length();
m_curBlock = -1; m_curBlock = -1;
if (m_blockSize > 0) if (m_blockSize > 0)
m_cacheData.reset(new atUint8[m_blockSize]); m_cacheData.reset(new atUint8[m_blockSize]);
} }
} // Athena } // namespace athena::io

View File

@ -1,233 +1,196 @@
#include "athena/FileReader.hpp" #include "athena/FileReader.hpp"
#include "win32_largefilewrapper.h" #include "win32_largefilewrapper.h"
namespace athena::io namespace athena::io {
{
FileReader::FileReader(std::string_view filename, atInt32 cacheSize, bool globalErr) FileReader::FileReader(std::string_view filename, atInt32 cacheSize, bool globalErr)
: m_fileHandle(nullptr), : m_fileHandle(nullptr), m_cacheData(nullptr), m_offset(0), m_globalErr(globalErr) {
m_cacheData(nullptr), m_filename = utility::utf8ToWide(filename);
m_offset(0), open();
m_globalErr(globalErr) setCacheSize(cacheSize);
{
m_filename = utility::utf8ToWide(filename);
open();
setCacheSize(cacheSize);
} }
FileReader::FileReader(std::wstring_view filename, atInt32 cacheSize, bool globalErr) FileReader::FileReader(std::wstring_view filename, atInt32 cacheSize, bool globalErr)
: m_fileHandle(nullptr), : m_fileHandle(nullptr), m_cacheData(nullptr), m_offset(0), m_globalErr(globalErr) {
m_cacheData(nullptr), m_filename = filename;
m_offset(0), open();
m_globalErr(globalErr) setCacheSize(cacheSize);
{
m_filename = filename;
open();
setCacheSize(cacheSize);
} }
FileReader::~FileReader() FileReader::~FileReader() {
{ if (isOpen())
if (isOpen()) close();
close();
} }
void FileReader::open() void FileReader::open() {
{ int attempt = 0;
int attempt = 0; do {
do
{
#if WINDOWS_STORE #if WINDOWS_STORE
m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
OPEN_EXISTING, nullptr);
#else #else
m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); FILE_ATTRIBUTE_NORMAL, nullptr);
#endif #endif
} while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100); } while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100);
if (m_fileHandle == INVALID_HANDLE_VALUE) if (m_fileHandle == INVALID_HANDLE_VALUE) {
{
m_fileHandle = 0;
std::string _filename = filename();
if (m_globalErr)
atError("File not found '%s'", _filename.c_str());
setError();
return;
}
// reset error
m_hasError = false;
}
void FileReader::close()
{
if (!m_fileHandle)
{
if (m_globalErr)
atError("Cannot close an unopened stream");
setError();
return;
}
CloseHandle(m_fileHandle);
m_fileHandle = 0; m_fileHandle = 0;
std::string _filename = filename();
if (m_globalErr)
atError("File not found '%s'", _filename.c_str());
setError();
return; return;
}
// reset error
m_hasError = false;
} }
void FileReader::seek(atInt64 pos, SeekOrigin origin) void FileReader::close() {
{ if (!m_fileHandle) {
if (!isOpen()) if (m_globalErr)
return; atError("Cannot close an unopened stream");
setError();
return;
}
// check block position CloseHandle(m_fileHandle);
if (m_blockSize > 0) m_fileHandle = 0;
{ return;
atUint64 oldOff = m_offset;
switch(origin)
{
case SeekOrigin::Begin:
m_offset = pos;
break;
case SeekOrigin::Current:
m_offset += pos;
break;
case SeekOrigin::End:
m_offset = length() - pos;
break;
}
if (m_offset > length())
{
oldOff = m_offset;
if (m_globalErr)
atError("Unable to seek in file");
setError();
return;
}
size_t block = m_offset / m_blockSize;
if (block != m_curBlock)
{
LARGE_INTEGER li;
li.QuadPart = block * m_blockSize;
SetFilePointerEx(m_fileHandle, li, nullptr, FILE_BEGIN);
ReadFile(m_fileHandle, m_cacheData.get(), m_blockSize, nullptr, nullptr);
m_curBlock = (atInt32)block;
}
}
else
{
LARGE_INTEGER li;
li.QuadPart = pos;
if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin)))
{
if (m_globalErr)
atError("Unable to seek in file");
setError();
}
}
} }
atUint64 FileReader::position() const void FileReader::seek(atInt64 pos, SeekOrigin origin) {
{ if (!isOpen())
if (!isOpen()) return;
{
if (m_globalErr) // check block position
atError("File not open"); if (m_blockSize > 0) {
return 0; atUint64 oldOff = m_offset;
switch (origin) {
case SeekOrigin::Begin:
m_offset = pos;
break;
case SeekOrigin::Current:
m_offset += pos;
break;
case SeekOrigin::End:
m_offset = length() - pos;
break;
}
if (m_offset > length()) {
oldOff = m_offset;
if (m_globalErr)
atError("Unable to seek in file");
setError();
return;
} }
if (m_blockSize > 0) size_t block = m_offset / m_blockSize;
return m_offset; if (block != m_curBlock) {
else LARGE_INTEGER li;
{ li.QuadPart = block * m_blockSize;
LARGE_INTEGER li = {}; SetFilePointerEx(m_fileHandle, li, nullptr, FILE_BEGIN);
LARGE_INTEGER res; ReadFile(m_fileHandle, m_cacheData.get(), m_blockSize, nullptr, nullptr);
SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT); m_curBlock = (atInt32)block;
return res.QuadPart;
} }
} else {
LARGE_INTEGER li;
li.QuadPart = pos;
if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin))) {
if (m_globalErr)
atError("Unable to seek in file");
setError();
}
}
} }
atUint64 FileReader::length() const atUint64 FileReader::position() const {
{ if (!isOpen()) {
if (!isOpen()) if (m_globalErr)
{ atError("File not open");
if (m_globalErr) return 0;
atError("File not open"); }
return 0;
}
if (m_blockSize > 0)
return m_offset;
else {
LARGE_INTEGER li = {};
LARGE_INTEGER res; LARGE_INTEGER res;
GetFileSizeEx(m_fileHandle, &res); SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT);
return res.QuadPart; return res.QuadPart;
}
} }
atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) atUint64 FileReader::length() const {
{ if (!isOpen()) {
if (!isOpen()) if (m_globalErr)
{ atError("File not open");
if (m_globalErr) return 0;
atError("File not open for reading"); }
setError();
return 0;
}
if (m_blockSize <= 0) LARGE_INTEGER res;
{ GetFileSizeEx(m_fileHandle, &res);
DWORD ret = 0; return res.QuadPart;
ReadFile(m_fileHandle, buf, len, &ret, nullptr);
return ret;
}
else
{
LARGE_INTEGER fs;
GetFileSizeEx(m_fileHandle, &fs);
if (m_offset >= atUint64(fs.QuadPart))
return 0;
if (m_offset + len >= atUint64(fs.QuadPart))
len = fs.QuadPart - m_offset;
size_t block = m_offset / m_blockSize;
atUint64 cacheOffset = m_offset % m_blockSize;
atUint64 cacheSize;
atUint64 rem = len;
atUint8* dst = (atUint8*)buf;
while (rem)
{
if (block != m_curBlock)
{
LARGE_INTEGER li;
li.QuadPart = block * m_blockSize;
SetFilePointerEx(m_fileHandle, li, nullptr, FILE_BEGIN);
ReadFile(m_fileHandle, m_cacheData.get(), m_blockSize, nullptr, nullptr);
m_curBlock = (atInt32)block;
}
cacheSize = rem;
if (cacheSize + cacheOffset > m_blockSize)
cacheSize = m_blockSize - cacheOffset;
memmove(dst, m_cacheData.get() + cacheOffset, cacheSize);
dst += cacheSize;
rem -= cacheSize;
cacheOffset = 0;
++block;
}
m_offset += len;
return dst - (atUint8*)buf;
}
} }
void FileReader::setCacheSize(const atInt32 blockSize) atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) {
{ if (!isOpen()) {
m_blockSize = blockSize; if (m_globalErr)
atError("File not open for reading");
setError();
return 0;
}
if (m_blockSize > length()) if (m_blockSize <= 0) {
m_blockSize = (atInt32)length(); DWORD ret = 0;
ReadFile(m_fileHandle, buf, len, &ret, nullptr);
return ret;
} else {
LARGE_INTEGER fs;
GetFileSizeEx(m_fileHandle, &fs);
if (m_offset >= atUint64(fs.QuadPart))
return 0;
if (m_offset + len >= atUint64(fs.QuadPart))
len = fs.QuadPart - m_offset;
m_curBlock = -1; size_t block = m_offset / m_blockSize;
if (m_blockSize > 0) atUint64 cacheOffset = m_offset % m_blockSize;
m_cacheData.reset(new atUint8[m_blockSize]); atUint64 cacheSize;
atUint64 rem = len;
atUint8* dst = (atUint8*)buf;
while (rem) {
if (block != m_curBlock) {
LARGE_INTEGER li;
li.QuadPart = block * m_blockSize;
SetFilePointerEx(m_fileHandle, li, nullptr, FILE_BEGIN);
ReadFile(m_fileHandle, m_cacheData.get(), m_blockSize, nullptr, nullptr);
m_curBlock = (atInt32)block;
}
cacheSize = rem;
if (cacheSize + cacheOffset > m_blockSize)
cacheSize = m_blockSize - cacheOffset;
memmove(dst, m_cacheData.get() + cacheOffset, cacheSize);
dst += cacheSize;
rem -= cacheSize;
cacheOffset = 0;
++block;
}
m_offset += len;
return dst - (atUint8*)buf;
}
} }
} // Athena void FileReader::setCacheSize(const atInt32 blockSize) {
m_blockSize = blockSize;
if (m_blockSize > length())
m_blockSize = (atInt32)length();
m_curBlock = -1;
if (m_blockSize > 0)
m_cacheData.reset(new atUint8[m_blockSize]);
}
} // namespace athena::io

View File

@ -1,32 +1,27 @@
#include "athena/FileWriter.hpp" #include "athena/FileWriter.hpp"
namespace athena::io namespace athena::io {
{ void TransactionalFileWriter::seek(atInt64 pos, SeekOrigin origin) {
void TransactionalFileWriter::seek(atInt64 pos, SeekOrigin origin) switch (origin) {
{ case SeekOrigin::Begin:
switch (origin) m_position = pos;
{ break;
case SeekOrigin::Begin: case SeekOrigin::Current:
m_position = pos; m_position += pos;
break; break;
case SeekOrigin::Current: case SeekOrigin::End:
m_position += pos; break;
break; }
case SeekOrigin::End:
break;
}
} }
void TransactionalFileWriter::writeUBytes(const atUint8* data, atUint64 len) void TransactionalFileWriter::writeUBytes(const atUint8* data, atUint64 len) {
{ atUint64 neededSz = m_position + len;
atUint64 neededSz = m_position + len; if (neededSz > m_deferredBuffer.size()) {
if (neededSz > m_deferredBuffer.size()) m_deferredBuffer.reserve(neededSz * 2);
{ m_deferredBuffer.resize(neededSz);
m_deferredBuffer.reserve(neededSz * 2); }
m_deferredBuffer.resize(neededSz);
}
memmove(m_deferredBuffer.data() + m_position, data, len); memmove(m_deferredBuffer.data() + m_position, data, len);
m_position += len; m_position += len;
}
} }
} // namespace athena::io

View File

@ -1,139 +1,114 @@
#include "athena/FileWriter.hpp" #include "athena/FileWriter.hpp"
#if __APPLE__ || __FreeBSD__ #if __APPLE__ || __FreeBSD__
#include "osx_largefilewrapper.h" #include "osx_largefilewrapper.h"
#elif GEKKO || __SWITCH__ #elif GEKKO || __SWITCH__
#include "gekko_support.h" #include "gekko_support.h"
#include "osx_largefilewrapper.h" #include "osx_largefilewrapper.h"
#endif #endif
#include <unistd.h> #include <unistd.h>
namespace athena::io namespace athena::io {
{
FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr) FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr)
: m_fileHandle(NULL), : m_fileHandle(NULL), m_globalErr(globalErr) {
m_globalErr(globalErr)
{
#if _WIN32 #if _WIN32
m_filename = utility::utf8ToWide(filename); m_filename = utility::utf8ToWide(filename);
#else #else
m_filename = filename; m_filename = filename;
#endif #endif
open(overwrite); open(overwrite);
} }
FileWriter::FileWriter(std::wstring_view filename, bool overwrite, bool globalErr) FileWriter::FileWriter(std::wstring_view filename, bool overwrite, bool globalErr)
: m_fileHandle(NULL), : m_fileHandle(NULL), m_globalErr(globalErr) {
m_globalErr(globalErr)
{
#if _WIN32 #if _WIN32
m_filename = filename; m_filename = filename;
#else #else
m_filename = utility::wideToUtf8(filename); m_filename = utility::wideToUtf8(filename);
#endif #endif
open(overwrite); open(overwrite);
} }
FileWriter::~FileWriter() FileWriter::~FileWriter() {
{ if (isOpen())
if (isOpen()) close();
close();
} }
void FileWriter::open(bool overwrite) void FileWriter::open(bool overwrite) {
{ if (overwrite) {
if (overwrite)
{
std::string tmpFilename = m_filename + '~';
m_fileHandle = fopen(tmpFilename.c_str(), "w+b");
}
else
{
m_fileHandle = fopen(m_filename.c_str(), "a+b");
if (m_fileHandle)
{
fclose(m_fileHandle);
m_fileHandle = fopen(m_filename.c_str(), "r+b");
}
}
if (!m_fileHandle)
{
if (m_globalErr)
atError("Unable to open file '%s'", filename().c_str());
setError();
return;
}
// reset error
m_hasError = false;
}
void FileWriter::close()
{
if (!m_fileHandle)
{
if (m_globalErr)
atError("Cannot close an unopened stream");
setError();
return;
}
fclose(m_fileHandle);
m_fileHandle = NULL;
std::string tmpFilename = m_filename + '~'; std::string tmpFilename = m_filename + '~';
m_fileHandle = fopen(tmpFilename.c_str(), "w+b");
} else {
m_fileHandle = fopen(m_filename.c_str(), "a+b");
if (m_fileHandle) {
fclose(m_fileHandle);
m_fileHandle = fopen(m_filename.c_str(), "r+b");
}
}
if (!m_fileHandle) {
if (m_globalErr)
atError("Unable to open file '%s'", filename().c_str());
setError();
return;
}
// reset error
m_hasError = false;
}
void FileWriter::close() {
if (!m_fileHandle) {
if (m_globalErr)
atError("Cannot close an unopened stream");
setError();
return;
}
fclose(m_fileHandle);
m_fileHandle = NULL;
std::string tmpFilename = m_filename + '~';
#ifdef __SWITCH__ #ifdef __SWITCH__
/* Due to Horizon not being a fully POSIX compatible OS, we need to make sure the file *does not* exist before attempting to rename */ /* Due to Horizon not being a fully POSIX compatible OS, we need to make sure the file *does not* exist before
unlink(m_filename.c_str()); * attempting to rename */
unlink(m_filename.c_str());
#endif #endif
rename(tmpFilename.c_str(), m_filename.c_str()); rename(tmpFilename.c_str(), m_filename.c_str());
} }
void FileWriter::seek(atInt64 pos, SeekOrigin origin) void FileWriter::seek(atInt64 pos, SeekOrigin origin) {
{ if (!isOpen()) {
if (!isOpen()) if (m_globalErr)
{ atError("Unable to seek in file, not open");
if (m_globalErr) setError();
atError("Unable to seek in file, not open"); return;
setError(); }
return;
}
if (fseeko64(m_fileHandle, pos, (int)origin) != 0) if (fseeko64(m_fileHandle, pos, (int)origin) != 0) {
{ if (m_globalErr)
if (m_globalErr) atError("Unable to seek in file");
atError("Unable to seek in file"); setError();
setError(); }
}
} }
atUint64 FileWriter::position() const atUint64 FileWriter::position() const { return ftello64(m_fileHandle); }
{
return ftello64(m_fileHandle);
}
atUint64 FileWriter::length() const atUint64 FileWriter::length() const { return utility::fileSize(m_filename); }
{
return utility::fileSize(m_filename);
}
void FileWriter::writeUBytes(const atUint8* data, atUint64 len) void FileWriter::writeUBytes(const atUint8* data, atUint64 len) {
{ if (!isOpen()) {
if (!isOpen()) if (m_globalErr)
{ atError("File not open for writing");
if (m_globalErr) setError();
atError("File not open for writing"); return;
setError(); }
return;
}
if (fwrite(data, 1, len, m_fileHandle) != len) if (fwrite(data, 1, len, m_fileHandle) != len) {
{ if (m_globalErr)
if (m_globalErr) atError("Unable to write to stream");
atError("Unable to write to stream"); setError();
setError(); }
}
} }
} // Athena } // namespace athena::io

View File

@ -1,140 +1,114 @@
#include "athena/FileWriter.hpp" #include "athena/FileWriter.hpp"
#include "win32_largefilewrapper.h" #include "win32_largefilewrapper.h"
namespace athena::io namespace athena::io {
{
FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr) FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr)
: m_fileHandle(0), : m_fileHandle(0), m_globalErr(globalErr) {
m_globalErr(globalErr) m_filename = utility::utf8ToWide(filename);
{ open(overwrite);
m_filename = utility::utf8ToWide(filename);
open(overwrite);
} }
FileWriter::FileWriter(std::wstring_view filename, bool overwrite, bool globalErr) FileWriter::FileWriter(std::wstring_view filename, bool overwrite, bool globalErr)
: m_fileHandle(0), : m_fileHandle(0), m_globalErr(globalErr) {
m_globalErr(globalErr) m_filename = filename;
{ open(overwrite);
m_filename = filename;
open(overwrite);
} }
FileWriter::~FileWriter() FileWriter::~FileWriter() {
{ if (isOpen())
if (isOpen()) close();
close();
} }
void FileWriter::open(bool overwrite) void FileWriter::open(bool overwrite) {
{ int attempt = 0;
int attempt = 0; do {
do if (overwrite) {
{ std::wstring tmpFilename = m_filename + L'~';
if (overwrite)
{
std::wstring tmpFilename = m_filename + L'~';
#if WINDOWS_STORE #if WINDOWS_STORE
m_fileHandle = CreateFile2(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, m_fileHandle = CreateFile2(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, CREATE_ALWAYS, nullptr);
CREATE_ALWAYS, nullptr);
#else #else
m_fileHandle = CreateFileW(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, m_fileHandle = CreateFileW(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS,
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); FILE_ATTRIBUTE_NORMAL, nullptr);
#endif #endif
} } else {
else
{
#if WINDOWS_STORE #if WINDOWS_STORE
m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_ALWAYS, nullptr);
OPEN_ALWAYS, nullptr);
#else #else
m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS,
nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); FILE_ATTRIBUTE_NORMAL, nullptr);
#endif #endif
}
} while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100);
if (m_fileHandle == INVALID_HANDLE_VALUE)
{
m_fileHandle = 0;
if (m_globalErr)
atError("Unable to open file '%s'", filename().c_str());
setError();
return;
} }
} while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100);
// reset error if (m_fileHandle == INVALID_HANDLE_VALUE) {
m_hasError = false;
}
void FileWriter::close()
{
if (!m_fileHandle)
{
if (m_globalErr)
atError("Cannot close an unopened stream");
setError();
return;
}
FlushFileBuffers(m_fileHandle);
CloseHandle(m_fileHandle);
m_fileHandle = 0; m_fileHandle = 0;
if (m_globalErr)
atError("Unable to open file '%s'", filename().c_str());
setError();
return;
}
std::wstring tmpFilename = m_filename + L'~'; // reset error
MoveFileExW(tmpFilename.c_str(), m_filename.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH); m_hasError = false;
} }
void FileWriter::seek(atInt64 pos, SeekOrigin origin) void FileWriter::close() {
{ if (!m_fileHandle) {
if (!isOpen()) if (m_globalErr)
{ atError("Cannot close an unopened stream");
if (m_globalErr) setError();
atError("Unable to seek in file, not open"); return;
setError(); }
return;
}
LARGE_INTEGER li; FlushFileBuffers(m_fileHandle);
li.QuadPart = pos; CloseHandle(m_fileHandle);
if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin))) m_fileHandle = 0;
{
if (m_globalErr) std::wstring tmpFilename = m_filename + L'~';
atError("Unable to seek in file"); MoveFileExW(tmpFilename.c_str(), m_filename.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
setError();
}
} }
atUint64 FileWriter::position() const void FileWriter::seek(atInt64 pos, SeekOrigin origin) {
{ if (!isOpen()) {
LARGE_INTEGER li = {}; if (m_globalErr)
LARGE_INTEGER res; atError("Unable to seek in file, not open");
SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT); setError();
return res.QuadPart; return;
}
LARGE_INTEGER li;
li.QuadPart = pos;
if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin))) {
if (m_globalErr)
atError("Unable to seek in file");
setError();
}
} }
atUint64 FileWriter::length() const atUint64 FileWriter::position() const {
{ LARGE_INTEGER li = {};
return utility::fileSize(m_filename); LARGE_INTEGER res;
SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT);
return res.QuadPart;
} }
void FileWriter::writeUBytes(const atUint8* data, atUint64 len) atUint64 FileWriter::length() const { return utility::fileSize(m_filename); }
{
if (!isOpen())
{
if (m_globalErr)
atError("File not open for writing");
setError();
return;
}
DWORD ret = 0; void FileWriter::writeUBytes(const atUint8* data, atUint64 len) {
WriteFile(m_fileHandle, data, len, &ret, nullptr); if (!isOpen()) {
if (ret != len) if (m_globalErr)
{ atError("File not open for writing");
if (m_globalErr) setError();
atError("Unable to write to stream"); return;
setError(); }
}
DWORD ret = 0;
WriteFile(m_fileHandle, data, len, &ret, nullptr);
if (ret != len) {
if (m_globalErr)
atError("Unable to write to stream");
setError();
}
} }
} // Athena } // namespace athena::io

View File

@ -4,80 +4,69 @@
#include <cstdarg> #include <cstdarg>
#include <cstdlib> #include <cstdlib>
std::ostream& operator<<(std::ostream& os, const athena::SeekOrigin& origin) std::ostream& operator<<(std::ostream& os, const athena::SeekOrigin& origin) {
{ switch (origin) {
switch (origin) case athena::SeekOrigin::Begin:
{ os << "Begin";
case athena::SeekOrigin::Begin: break;
os << "Begin";
break;
case athena::SeekOrigin::Current: case athena::SeekOrigin::Current:
os << "Current"; os << "Current";
break; break;
case athena::SeekOrigin::End: case athena::SeekOrigin::End:
os << "End"; os << "End";
break; break;
} }
return os; return os;
} }
std::ostream& operator<<(std::ostream& os, const athena::Endian& endian) {
switch (endian) {
case athena::Endian::Little:
os << "LittleEndian";
break;
std::ostream& operator<<(std::ostream& os, const athena::Endian& endian) case athena::Endian::Big:
{ os << "BigEndian";
switch (endian) break;
{ }
case athena::Endian::Little:
os << "LittleEndian";
break;
case athena::Endian::Big: return os;
os << "BigEndian";
break;
}
return os;
} }
static void __defaultExceptionHandler(athena::error::Level level, const char* file, const char* function, int line,
const char* fmt, ...) {
std::string levelStr;
switch (level) {
case athena::error::Level::Warning:
levelStr = "[WARNING] ";
break;
case athena::error::Level::Error:
levelStr = "[ERROR ] ";
break;
case athena::error::Level::Fatal:
levelStr = "[FATAL ] ";
break;
default:
break;
}
static void __defaultExceptionHandler(athena::error::Level level, const char* file, const char* function, int line, const char* fmt, ...) va_list vl;
{ va_start(vl, fmt);
std::string levelStr; std::string msg = athena::utility::vsprintf(fmt, vl);
switch (level) va_end(vl);
{ std::cerr << levelStr << " " << file << " " << function << "(" << line << "): " << msg << std::endl;
case athena::error::Level::Warning:
levelStr = "[WARNING] ";
break;
case athena::error::Level::Error:
levelStr = "[ERROR ] ";
break;
case athena::error::Level::Fatal:
levelStr = "[FATAL ] ";
break;
default: break;
}
va_list vl;
va_start(vl, fmt);
std::string msg = athena::utility::vsprintf(fmt, vl);
va_end(vl);
std::cerr << levelStr << " " << file << " " << function << "(" << line << "): " << msg << std::endl;
} }
static atEXCEPTION_HANDLER g_atExceptionHandler = __defaultExceptionHandler; static atEXCEPTION_HANDLER g_atExceptionHandler = __defaultExceptionHandler;
atEXCEPTION_HANDLER atGetExceptionHandler() atEXCEPTION_HANDLER atGetExceptionHandler() { return g_atExceptionHandler; }
{
return g_atExceptionHandler;
}
void atSetExceptionHandler(atEXCEPTION_HANDLER func) {
void atSetExceptionHandler(atEXCEPTION_HANDLER func) if (func)
{ g_atExceptionHandler = func;
if (func) else
g_atExceptionHandler = func; g_atExceptionHandler = __defaultExceptionHandler;
else
g_atExceptionHandler = __defaultExceptionHandler;
} }

View File

@ -1,44 +1,37 @@
#include "athena/MCFile.hpp" #include "athena/MCFile.hpp"
namespace athena namespace athena {
{
const char MCFile::VERSION_EU_JP[33] = "AGBZELDA:THE MINISH CAP:ZELDA 3\0"; const char MCFile::VERSION_EU_JP[33] = "AGBZELDA:THE MINISH CAP:ZELDA 3\0";
const char MCFile::VERSION_US[33] = "AGBZELDA:THE MINISH CAP:ZELDA 5\0"; const char MCFile::VERSION_US[33] = "AGBZELDA:THE MINISH CAP:ZELDA 5\0";
MCFile::MCFile() MCFile::MCFile() {}
{
}
// TODO: Rewrite this to be more optimized, the current solution takes quite a few cycles // TODO: Rewrite this to be more optimized, the current solution takes quite a few cycles
atUint8* reverse(atUint8* data, atUint32 length) atUint8* reverse(atUint8* data, atUint32 length) {
{ atUint32 a = 0;
atUint32 a = 0; atUint32 swap;
atUint32 swap;
for (; a < --length; a++) for (; a < --length; a++) {
{ swap = data[a];
swap = data[a]; data[a] = data[length];
data[a] = data[length]; data[length] = swap;
data[length] = swap; }
}
return data; return data;
} }
atUint8* MCFile::unscramble(atUint8* data, atUint64 length) atUint8* MCFile::unscramble(atUint8* data, atUint64 length) {
{ if (!data)
if (!data) return nullptr;
return nullptr;
for (atUint32 i = 0; i < length; i += 8) for (atUint32 i = 0; i < length; i += 8) {
{ atUint32 block1 = *(atUint32*)reverse((data + i), 4);
atUint32 block1 = *(atUint32*)reverse((data + i), 4); atUint32 block2 = *(atUint32*)reverse((data + i + 4), 4);
atUint32 block2 = *(atUint32*)reverse((data + i + 4), 4); *(atUint32*)(data + i) = block2;
*(atUint32*)(data + i) = block2; *(atUint32*)(data + i + 4) = block1;
*(atUint32*)(data + i + 4) = block1; }
}
return data; return data;
} }
} // zelda } // namespace athena

View File

@ -1,33 +1,23 @@
#include "athena/MCFileReader.hpp" #include "athena/MCFileReader.hpp"
#include "athena/MCFile.hpp" #include "athena/MCFile.hpp"
namespace athena namespace athena {
{
namespace io namespace io {
{
static const atUint32 SCRAMBLE_VALUE = 0x5A424741; static const atUint32 SCRAMBLE_VALUE = 0x5A424741;
MCFileReader::MCFileReader(atUint8* data, atUint64 length) MCFileReader::MCFileReader(atUint8* data, atUint64 length) : MemoryCopyReader(data, length) {}
: MemoryCopyReader(data, length)
{ MCFileReader::MCFileReader(const std::string& filename) : MemoryCopyReader(filename) {}
MCFile* MCFileReader::readFile() {
bool isScrambled = readUint32() != SCRAMBLE_VALUE;
m_position = 0;
if (isScrambled)
MCFile::unscramble(m_dataCopy.get(), m_length);
return nullptr;
} }
MCFileReader::MCFileReader(const std::string& filename) } // namespace io
: MemoryCopyReader(filename) } // namespace athena
{
}
MCFile* MCFileReader::readFile()
{
bool isScrambled = readUint32() != SCRAMBLE_VALUE;
m_position = 0;
if (isScrambled)
MCFile::unscramble(m_dataCopy.get(), m_length);
return nullptr;
}
} // io
} // zelda

View File

@ -1,49 +1,39 @@
#include "athena/MCFileWriter.hpp" #include "athena/MCFileWriter.hpp"
namespace athena::io namespace athena::io {
{
MCFileWriter::MCFileWriter(atUint8* data, atUint64 length) MCFileWriter::MCFileWriter(atUint8* data, atUint64 length) : MemoryCopyWriter(data, length) {}
: MemoryCopyWriter(data, length)
{
}
MCFileWriter::MCFileWriter(const std::string& filename) MCFileWriter::MCFileWriter(const std::string& filename) : MemoryCopyWriter(filename) {}
: MemoryCopyWriter(filename)
{
}
// TODO: Check the implementation, it seems to work fine, however it's not exactly correct, // TODO: Check the implementation, it seems to work fine, however it's not exactly correct,
// looking at the disassembly, MC seems to do some weird checking that isn't being done with this solution // looking at the disassembly, MC seems to do some weird checking that isn't being done with this solution
// need to figure out what it's doing and whether it's relevant to the checksum. // need to figure out what it's doing and whether it's relevant to the checksum.
atUint16 MCFileWriter::calculateSlotChecksum(atUint32 game) atUint16 MCFileWriter::calculateSlotChecksum(atUint32 game) {
{ atUint16 first = calculateChecksum((m_data + 0x34 + (0x10 * game)), 4);
atUint16 first = calculateChecksum((m_data + 0x34 + (0x10 * game)), 4); atUint16 second = calculateChecksum((m_data + 0x80 + (0x500 * game)), 0x500);
atUint16 second = calculateChecksum((m_data + 0x80 + (0x500 * game)), 0x500);
first = (first + second) & 0xFFFF; first = (first + second) & 0xFFFF;
atUint16 result = first << 16; atUint16 result = first << 16;
second = ~first & 0xFFFF; second = ~first & 0xFFFF;
second += 1; second += 1;
result += second; result += second;
return result; return result;
} }
atUint16 MCFileWriter::calculateChecksum(atUint8* data, atUint32 length) atUint16 MCFileWriter::calculateChecksum(atUint8* data, atUint32 length) {
{ atUint16 sum = 0;
atUint16 sum = 0; int i = length;
int i = length;
for (atUint32 j = 0; j < length; j += 2) for (atUint32 j = 0; j < length; j += 2) {
{ sum += *(atUint16*)(data + j) ^ i;
sum += *(atUint16*)(data + j) ^ i; i -= 2;
i -= 2; }
}
sum &= 0xFFFF; sum &= 0xFFFF;
return sum; return sum;
} }
} // zelda } // namespace athena::io

View File

@ -1,11 +1,8 @@
#include "athena/MCSlot.hpp" #include "athena/MCSlot.hpp"
namespace athena namespace athena {
{
MCSlot::MCSlot(std::unique_ptr<atUint8[]>&& data, atUint32 length) MCSlot::MCSlot(std::unique_ptr<atUint8[]>&& data, atUint32 length)
: ZQuestFile(ZQuestFile::MC, Endian::Little, std::move(data), length) : ZQuestFile(ZQuestFile::MC, Endian::Little, std::move(data), length) {}
{
}
} // Athena } // namespace athena

View File

@ -14,184 +14,156 @@
#undef min #undef min
#undef max #undef max
namespace athena::io namespace athena::io {
{
MemoryReader::MemoryReader(const void* data, atUint64 length, bool takeOwnership, bool globalErr) MemoryReader::MemoryReader(const void* data, atUint64 length, bool takeOwnership, bool globalErr)
: m_data(data), : m_data(data), m_length(length), m_position(0), m_owns(takeOwnership), m_globalErr(globalErr) {
m_length(length), if (!data) {
m_position(0), if (m_globalErr)
m_owns(takeOwnership), atError("data cannot be NULL");
m_globalErr(globalErr) setError();
{ return;
if (!data) }
{
if (m_globalErr)
atError("data cannot be NULL");
setError();
return;
}
} }
MemoryReader::~MemoryReader() MemoryReader::~MemoryReader() {
{ if (m_owns)
if (m_owns) delete[] reinterpret_cast<const atUint8*>(m_data);
delete[] reinterpret_cast<const atUint8*>(m_data);
} }
MemoryCopyReader::MemoryCopyReader(const void* data, atUint64 length) MemoryCopyReader::MemoryCopyReader(const void* data, atUint64 length) : MemoryReader(data, length, false) {
: MemoryReader(data, length, false) if (!data) {
{ if (m_globalErr)
if (!data) atError("data cannot be NULL");
{ setError();
if (m_globalErr) return;
atError("data cannot be NULL"); }
setError();
return; m_dataCopy.reset(new atUint8[m_length]);
m_data = m_dataCopy.get();
memmove(m_dataCopy.get(), data, m_length);
}
void MemoryReader::seek(atInt64 position, SeekOrigin origin) {
switch (origin) {
case SeekOrigin::Begin:
if ((position < 0 || (atInt64)position > (atInt64)m_length)) {
if (m_globalErr)
atFatal("Position %0.8X outside stream bounds ", position);
m_position = m_length;
setError();
return;
} }
m_dataCopy.reset(new atUint8[m_length]); m_position = position;
m_data = m_dataCopy.get(); break;
memmove(m_dataCopy.get(), data, m_length);
}
void MemoryReader::seek(atInt64 position, SeekOrigin origin) case SeekOrigin::Current:
{ if ((((atInt64)m_position + position) < 0 || (m_position + position) > m_length)) {
switch (origin) if (m_globalErr)
{ atFatal("Position %0.8X outside stream bounds ", position);
case SeekOrigin::Begin: m_position = m_length;
if ((position < 0 || (atInt64)position > (atInt64)m_length)) setError();
{ return;
if (m_globalErr)
atFatal("Position %0.8X outside stream bounds ", position);
m_position = m_length;
setError();
return;
}
m_position = position;
break;
case SeekOrigin::Current:
if ((((atInt64)m_position + position) < 0 || (m_position + position) > m_length))
{
if (m_globalErr)
atFatal("Position %0.8X outside stream bounds ", position);
m_position = m_length;
setError();
return;
}
m_position += position;
break;
case SeekOrigin::End:
if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length))
{
if (m_globalErr)
atFatal("Position %0.8X outside stream bounds ", position);
m_position = m_length;
setError();
return;
}
m_position = m_length - position;
break;
}
}
void MemoryReader::setData(const atUint8* data, atUint64 length, bool takeOwnership)
{
if (m_owns)
delete[] static_cast<const atUint8*>(m_data);
m_data = (atUint8*)data;
m_length = length;
m_position = 0;
m_owns = takeOwnership;
}
void MemoryCopyReader::setData(const atUint8* data, atUint64 length)
{
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
memmove(m_dataCopy.get(), data, length);
m_length = length;
m_position = 0;
}
atUint8* MemoryReader::data() const
{
atUint8* ret = new atUint8[m_length];
memset(ret, 0, m_length);
memmove(ret, m_data, m_length);
return ret;
}
atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length)
{
if (m_position >= m_length)
{
if (m_globalErr)
atFatal("Position %0.8X outside stream bounds ", m_position);
m_position = m_length;
setError();
return 0;
} }
length = std::min(length, m_length - m_position); m_position += position;
memmove(buf, reinterpret_cast<const atUint8*>(m_data) + m_position, length); break;
m_position += length;
return length;
}
void MemoryCopyReader::loadData() case SeekOrigin::End:
{ if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length)) {
FILE* in; if (m_globalErr)
atUint64 length; atFatal("Position %0.8X outside stream bounds ", position);
in = fopen(m_filepath.c_str(), "rb"); m_position = m_length;
setError();
if (!in) return;
{
if (m_globalErr)
atError("Unable to open file '%s'", m_filepath.c_str());
setError();
return;
} }
rewind(in); m_position = m_length - position;
break;
length = utility::fileSize(m_filepath); }
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
atUint64 done = 0;
atUint64 blocksize = BLOCKSZ;
do
{
if (blocksize > length - done)
blocksize = length - done;
atInt64 ret = fread(m_dataCopy.get() + done, 1, blocksize, in);
if (ret < 0)
{
if (m_globalErr)
atError("Error reading data from disk");
setError();
return;
}
else if (ret == 0)
break;
done += ret;
}
while (done < length);
fclose(in);
m_length = length;
m_position = 0;
} }
void MemoryReader::setData(const atUint8* data, atUint64 length, bool takeOwnership) {
if (m_owns)
delete[] static_cast<const atUint8*>(m_data);
m_data = (atUint8*)data;
m_length = length;
m_position = 0;
m_owns = takeOwnership;
} }
void MemoryCopyReader::setData(const atUint8* data, atUint64 length) {
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
memmove(m_dataCopy.get(), data, length);
m_length = length;
m_position = 0;
}
atUint8* MemoryReader::data() const {
atUint8* ret = new atUint8[m_length];
memset(ret, 0, m_length);
memmove(ret, m_data, m_length);
return ret;
}
atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length) {
if (m_position >= m_length) {
if (m_globalErr)
atFatal("Position %0.8X outside stream bounds ", m_position);
m_position = m_length;
setError();
return 0;
}
length = std::min(length, m_length - m_position);
memmove(buf, reinterpret_cast<const atUint8*>(m_data) + m_position, length);
m_position += length;
return length;
}
void MemoryCopyReader::loadData() {
FILE* in;
atUint64 length;
in = fopen(m_filepath.c_str(), "rb");
if (!in) {
if (m_globalErr)
atError("Unable to open file '%s'", m_filepath.c_str());
setError();
return;
}
rewind(in);
length = utility::fileSize(m_filepath);
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
atUint64 done = 0;
atUint64 blocksize = BLOCKSZ;
do {
if (blocksize > length - done)
blocksize = length - done;
atInt64 ret = fread(m_dataCopy.get() + done, 1, blocksize, in);
if (ret < 0) {
if (m_globalErr)
atError("Error reading data from disk");
setError();
return;
} else if (ret == 0)
break;
done += ret;
} while (done < length);
fclose(in);
m_length = length;
m_position = 0;
}
} // namespace athena::io

View File

@ -9,309 +9,267 @@
#include <malloc.h> #include <malloc.h>
#endif // HW_RVL #endif // HW_RVL
namespace athena::io namespace athena::io {
{
MemoryWriter::MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership) MemoryWriter::MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership)
: m_data((atUint8*)data), : m_data((atUint8*)data), m_length(length), m_position(0), m_bufferOwned(takeOwnership) {
m_length(length), if (!data) {
m_position(0), atError("data cannot be NULL");
m_bufferOwned(takeOwnership) setError();
{ return;
if (!data) }
{
atError("data cannot be NULL");
setError();
return;
}
} }
MemoryWriter::~MemoryWriter() MemoryWriter::~MemoryWriter() {
{ if (m_bufferOwned)
if (m_bufferOwned) delete m_data;
delete m_data; m_data = nullptr;
m_data = nullptr; m_length = 0;
m_length = 0;
} }
MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) {
{ m_data = data;
m_data = data; m_length = length;
m_length = length; m_position = 0;
m_position = 0; m_bufferOwned = false;
m_bufferOwned = false;
if (length == 0) if (length == 0) {
{ atError("length cannot be 0");
atError("length cannot be 0"); setError();
setError(); return;
return; }
} m_dataCopy.reset(new atUint8[length]);
m_dataCopy.reset(new atUint8[length]); m_data = m_dataCopy.get();
m_data = m_dataCopy.get(); if (data)
if (data)
memmove(m_data, data, length);
}
MemoryCopyWriter::MemoryCopyWriter(std::string_view filename)
{
m_filepath = filename;
m_length = 0x10;
m_position = 0;
m_dataCopy.reset(new atUint8[m_length]);
m_data = m_dataCopy.get();
m_bufferOwned = false;
if (!m_data)
{
atError("Could not allocate memory!");
setError();
return;
}
}
void MemoryWriter::seek(atInt64 position, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin::Begin:
if (position < 0)
{
atError("Position outside stream bounds");
setError();
return;
}
if ((atUint64)position > m_length)
{
atError("data exceeds available buffer space");
setError();
return;
}
m_position = position;
break;
case SeekOrigin::Current:
if ((((atInt64)m_position + position) < 0))
{
atError("Position outside stream bounds");
setError();
return;
}
if (m_position + position > m_length)
{
atError("data exceeds available buffer space");
setError();
return;
}
m_position += position;
break;
case SeekOrigin::End:
if (((atInt64)m_length - position) < 0)
{
atError("Position outside stream bounds");
setError();
return;
}
if ((atUint64)position > m_length)
{
atError("data exceeds available buffer space");
setError();
return;
}
m_position = m_length - position;
break;
}
}
void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin::Begin:
if (position < 0)
{
atError("Position outside stream bounds");
setError();
return;
}
if ((atUint64)position > m_length)
resize(position);
m_position = position;
break;
case SeekOrigin::Current:
if ((((atInt64)m_position + position) < 0))
{
atError("Position outside stream bounds");
setError();
return;
}
if (m_position + position > m_length)
resize(m_position + position);
m_position += position;
break;
case SeekOrigin::End:
if (((atInt64)m_length - position) < 0)
{
atError("Position outside stream bounds");
setError();
return;
}
if ((atUint64)position > m_length)
resize(position);
m_position = m_length - position;
break;
}
}
void MemoryWriter::setData(atUint8* data, atUint64 length, bool takeOwnership)
{
if (m_bufferOwned)
delete m_data;
m_data = (atUint8*)data;
m_length = length;
m_position = 0;
m_bufferOwned = takeOwnership;
}
void MemoryCopyWriter::setData(const atUint8* data, atUint64 length)
{
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
memmove(m_data, data, length); memmove(m_data, data, length);
m_length = length;
m_position = 0;
m_bufferOwned = false;
} }
atUint8* MemoryWriter::data() const MemoryCopyWriter::MemoryCopyWriter(std::string_view filename) {
{ m_filepath = filename;
atUint8* ret = new atUint8[m_length]; m_length = 0x10;
memset(ret, 0, m_length); m_position = 0;
memmove(ret, m_data, m_length); m_dataCopy.reset(new atUint8[m_length]);
return ret; m_data = m_dataCopy.get();
m_bufferOwned = false;
if (!m_data) {
atError("Could not allocate memory!");
setError();
return;
}
} }
void MemoryWriter::seek(atInt64 position, SeekOrigin origin) {
void MemoryWriter::save(std::string_view filename) switch (origin) {
{ case SeekOrigin::Begin:
if (filename.empty() && m_filepath.empty()) if (position < 0) {
{ atError("Position outside stream bounds");
atError("No file specified, cannot save."); setError();
setError(); return;
return;
} }
if (!filename.empty()) if ((atUint64)position > m_length) {
m_filepath = filename; atError("data exceeds available buffer space");
setError();
FILE* out = fopen(m_filepath.c_str(), "wb"); return;
if (!out)
{
atError("Unable to open file '%s'", m_filepath.c_str());
setError();
return;
} }
atUint64 done = 0; m_position = position;
atUint64 blocksize = BLOCKSZ; break;
do case SeekOrigin::Current:
{ if ((((atInt64)m_position + position) < 0)) {
if (blocksize > m_length - done) atError("Position outside stream bounds");
blocksize = m_length - done; setError();
return;
atInt64 ret = fwrite(m_data + done, 1, blocksize, out);
if (ret < 0)
{
atError("Error writing data to disk");
setError();
return;
}
else if (ret == 0)
break;
done += blocksize;
} }
while (done < m_length);
fclose(out); if (m_position + position > m_length) {
atError("data exceeds available buffer space");
setError();
return;
}
m_position += position;
break;
case SeekOrigin::End:
if (((atInt64)m_length - position) < 0) {
atError("Position outside stream bounds");
setError();
return;
}
if ((atUint64)position > m_length) {
atError("data exceeds available buffer space");
setError();
return;
}
m_position = m_length - position;
break;
}
} }
void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin) {
{ switch (origin) {
if (!data) case SeekOrigin::Begin:
{ if (position < 0) {
atError("data cannnot be NULL"); atError("Position outside stream bounds");
setError(); setError();
return; return;
} }
if (m_position + length > m_length) if ((atUint64)position > m_length)
{ resize(position);
atError("data length exceeds available buffer space");
setError(); m_position = position;
return; break;
case SeekOrigin::Current:
if ((((atInt64)m_position + position) < 0)) {
atError("Position outside stream bounds");
setError();
return;
} }
memmove(reinterpret_cast<atInt8*>(m_data + m_position), data, length); if (m_position + position > m_length)
resize(m_position + position);
m_position += length; m_position += position;
break;
case SeekOrigin::End:
if (((atInt64)m_length - position) < 0) {
atError("Position outside stream bounds");
setError();
return;
}
if ((atUint64)position > m_length)
resize(position);
m_position = m_length - position;
break;
}
} }
void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length) void MemoryWriter::setData(atUint8* data, atUint64 length, bool takeOwnership) {
{ if (m_bufferOwned)
if (!data) delete m_data;
{
atError("data cannnot be NULL");
setError();
return;
}
if (m_position + length > m_length) m_data = (atUint8*)data;
resize(m_position + length); m_length = length;
m_position = 0;
memmove(reinterpret_cast<atInt8*>(m_data + m_position), data, length); m_bufferOwned = takeOwnership;
m_position += length;
} }
void MemoryCopyWriter::resize(atUint64 newSize) void MemoryCopyWriter::setData(const atUint8* data, atUint64 length) {
{ m_dataCopy.reset(new atUint8[length]);
if (newSize < m_length) m_data = m_dataCopy.get();
{ memmove(m_data, data, length);
atError("New size cannot be less to the old size."); m_length = length;
return; m_position = 0;
} m_bufferOwned = false;
// Allocate and copy new buffer
atUint8* newArray = new atUint8[newSize];
memset(newArray, 0, newSize);
if (m_dataCopy)
memmove(newArray, m_dataCopy.get(), m_length);
m_dataCopy.reset(newArray);
// Swap the pointer and size out for the new ones.
m_data = newArray;
m_length = newSize;
} }
} // Athena atUint8* MemoryWriter::data() const {
atUint8* ret = new atUint8[m_length];
memset(ret, 0, m_length);
memmove(ret, m_data, m_length);
return ret;
}
void MemoryWriter::save(std::string_view filename) {
if (filename.empty() && m_filepath.empty()) {
atError("No file specified, cannot save.");
setError();
return;
}
if (!filename.empty())
m_filepath = filename;
FILE* out = fopen(m_filepath.c_str(), "wb");
if (!out) {
atError("Unable to open file '%s'", m_filepath.c_str());
setError();
return;
}
atUint64 done = 0;
atUint64 blocksize = BLOCKSZ;
do {
if (blocksize > m_length - done)
blocksize = m_length - done;
atInt64 ret = fwrite(m_data + done, 1, blocksize, out);
if (ret < 0) {
atError("Error writing data to disk");
setError();
return;
} else if (ret == 0)
break;
done += blocksize;
} while (done < m_length);
fclose(out);
}
void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) {
if (!data) {
atError("data cannnot be NULL");
setError();
return;
}
if (m_position + length > m_length) {
atError("data length exceeds available buffer space");
setError();
return;
}
memmove(reinterpret_cast<atInt8*>(m_data + m_position), data, length);
m_position += length;
}
void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length) {
if (!data) {
atError("data cannnot be NULL");
setError();
return;
}
if (m_position + length > m_length)
resize(m_position + length);
memmove(reinterpret_cast<atInt8*>(m_data + m_position), data, length);
m_position += length;
}
void MemoryCopyWriter::resize(atUint64 newSize) {
if (newSize < m_length) {
atError("New size cannot be less to the old size.");
return;
}
// Allocate and copy new buffer
atUint8* newArray = new atUint8[newSize];
memset(newArray, 0, newSize);
if (m_dataCopy)
memmove(newArray, m_dataCopy.get(), m_length);
m_dataCopy.reset(newArray);
// Swap the pointer and size out for the new ones.
m_data = newArray;
m_length = newSize;
}
} // namespace athena::io

View File

@ -3,200 +3,132 @@
#include "athena/FileNotFoundException.hpp" #include "athena/FileNotFoundException.hpp"
#include "athena/IOException.hpp" #include "athena/IOException.hpp"
namespace athena::io namespace athena::io {
{
PHYSFSFileReader::PHYSFSFileReader(const std::string& path) PHYSFSFileReader::PHYSFSFileReader(const std::string& path) : m_path(path), m_endian(Endian::LittleEndian) {
: m_path(path), if (!PHYSFS_exists(m_path.c_str()))
m_endian(Endian::LittleEndian) THROW_FILE_NOT_FOUND_EXCEPTION(path);
{
if (!PHYSFS_exists(m_path.c_str()))
THROW_FILE_NOT_FOUND_EXCEPTION(path);
m_handle = PHYSFS_openRead(path.c_str()); m_handle = PHYSFS_openRead(path.c_str());
m_length = PHYSFS_fileLength(m_handle); m_length = PHYSFS_fileLength(m_handle);
} }
atUint8* PHYSFSFileReader::data() atUint8* PHYSFSFileReader::data() { return readUBytes(length()); }
{
return readUBytes(length()); atUint64 PHYSFSFileReader::length() const { return m_length; }
atUint64 PHYSFSFileReader::position() const { return PHYSFS_tell(m_handle); }
bool PHYSFSFileReader::isOpen() const { return (m_handle != nullptr); }
void PHYSFSFileReader::seek(atInt64 position, SeekOrigin origin) {
atInt64 curPos = PHYSFS_tell(m_handle);
switch (origin) {
case SeekOrigin::Begin:
if ((position < 0 || (atInt64)position > (atInt64)m_length))
THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position);
PHYSFS_seek(m_handle, position);
break;
case SeekOrigin::Current:
if ((((atInt64)curPos + position) < 0 || (curPos + position) > m_length))
THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position);
PHYSFS_seek(m_handle, curPos + position);
break;
case SeekOrigin::End:
if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length))
THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position);
PHYSFS_seek(m_handle, m_length - position);
break;
}
} }
atUint64 PHYSFSFileReader::length() const atUint8 PHYSFSFileReader::readUByte() {
{ atUint8 val;
return m_length;
}
atUint64 PHYSFSFileReader::position() const if (!PHYSFS_read(m_handle, &val, 1, 1))
{
return PHYSFS_tell(m_handle);
}
bool PHYSFSFileReader::isOpen() const
{
return (m_handle != nullptr);
}
void PHYSFSFileReader::seek(atInt64 position, SeekOrigin origin)
{
atInt64 curPos = PHYSFS_tell(m_handle);
switch (origin)
{
case SeekOrigin::Begin:
if ((position < 0 || (atInt64)position > (atInt64)m_length))
THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position);
PHYSFS_seek(m_handle, position);
break;
case SeekOrigin::Current:
if ((((atInt64)curPos + position) < 0 || (curPos + position) > m_length))
THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position);
PHYSFS_seek(m_handle, curPos + position);
break;
case SeekOrigin::End:
if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length))
THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position);
PHYSFS_seek(m_handle, m_length - position);
break;
}
}
atUint8 PHYSFSFileReader::readUByte()
{
atUint8 val;
if (!PHYSFS_read(m_handle, &val, 1, 1))
THROW_IO_EXCEPTION("Position outside stream bounds");
return val;
}
atInt8 PHYSFSFileReader::readByte()
{
return readUByte();
}
atUint8* PHYSFSFileReader::readUBytes(atUint64 length)
{
atUint8* data = new atUint8[length];
if (PHYSFS_read(m_handle, data, 1, length) == length)
return data;
delete[] data;
THROW_IO_EXCEPTION("Position outside stream bounds"); THROW_IO_EXCEPTION("Position outside stream bounds");
return val;
} }
atInt8* PHYSFSFileReader::readBytes(atUint64 length) atInt8 PHYSFSFileReader::readByte() { return readUByte(); }
{
return (atInt8*)readUBytes(length); atUint8* PHYSFSFileReader::readUBytes(atUint64 length) {
atUint8* data = new atUint8[length];
if (PHYSFS_read(m_handle, data, 1, length) == length)
return data;
delete[] data;
THROW_IO_EXCEPTION("Position outside stream bounds");
} }
atUint16 PHYSFSFileReader::readUint16() atInt8* PHYSFSFileReader::readBytes(atUint64 length) { return (atInt8*)readUBytes(length); }
{
atUint16 val;
if (m_endian == Endian::BigEndian) atUint16 PHYSFSFileReader::readUint16() {
{ atUint16 val;
if (!PHYSFS_readUBE16(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
}
else if (!PHYSFS_readULE16(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
return val; if (m_endian == Endian::BigEndian) {
if (!PHYSFS_readUBE16(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
} else if (!PHYSFS_readULE16(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
return val;
} }
atInt16 PHYSFSFileReader::readInt16() atInt16 PHYSFSFileReader::readInt16() { return readUint16(); }
{
return readUint16(); atUint32 PHYSFSFileReader::readUint32() {
atUint32 val;
if (m_endian == Endian::BigEndian) {
if (!PHYSFS_readUBE32(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
} else if (!PHYSFS_readULE32(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
return val;
} }
atUint32 PHYSFSFileReader::readUint32() atInt32 PHYSFSFileReader::readInt32() { return readUint32(); }
{
atUint32 val;
if (m_endian == Endian::BigEndian) atUint64 PHYSFSFileReader::readUint64() {
{ atUint64 val;
if (!PHYSFS_readUBE32(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
}
else if (!PHYSFS_readULE32(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
return val; if (m_endian == Endian::BigEndian) {
if (!PHYSFS_readUBE64(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
} else if (!PHYSFS_readUBE64(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
return val;
} }
atInt32 PHYSFSFileReader::readInt32() atInt64 PHYSFSFileReader::readInt64() { return readUint64(); }
{
return readUint32();
}
atUint64 PHYSFSFileReader::readUint64() double PHYSFSFileReader::readDouble() { return static_cast<double>(readUint64()); }
{
atUint64 val;
if (m_endian == Endian::BigEndian) float PHYSFSFileReader::readFloat() { return static_cast<float>(readUint32()); }
{
if (!PHYSFS_readUBE64(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
}
else if (!PHYSFS_readUBE64(m_handle, &val))
THROW_IO_EXCEPTION("Position outside stream bounds");
return val; bool PHYSFSFileReader::readBool() { return (readByte() != 0); }
}
atInt64 PHYSFSFileReader::readInt64() bool PHYSFSFileReader::atEnd() const { return PHYSFS_eof(m_handle); }
{
return readUint64();
}
double PHYSFSFileReader::readDouble() void PHYSFSFileReader::setEndian(Endian endian) { m_endian = endian; }
{
return static_cast<double>(readUint64());
}
float PHYSFSFileReader::readFloat() Endian PHYSFSFileReader::endian() const { return m_endian; }
{
return static_cast<float>(readUint32());
}
bool PHYSFSFileReader::readBool() bool PHYSFSFileReader::isBigEndian() const { return m_endian == Endian::BigEndian; }
{
return (readByte() != 0);
}
bool PHYSFSFileReader::atEnd() const bool PHYSFSFileReader::isLittleEndian() const { return m_endian == Endian::LittleEndian; }
{
return PHYSFS_eof(m_handle);
}
void PHYSFSFileReader::setEndian(Endian endian) } // namespace athena::io
{
m_endian = endian;
}
Endian PHYSFSFileReader::endian() const
{
return m_endian;
}
bool PHYSFSFileReader::isBigEndian() const
{
return m_endian == Endian::BigEndian;
}
bool PHYSFSFileReader::isLittleEndian() const
{
return m_endian == Endian::LittleEndian;
}
}
#endif #endif

View File

@ -1,58 +1,35 @@
#include "athena/SkywardSwordFile.hpp" #include "athena/SkywardSwordFile.hpp"
#include "athena/SkywardSwordQuest.hpp" #include "athena/SkywardSwordQuest.hpp"
namespace athena namespace athena {
{
SkywardSwordFile::SkywardSwordFile() SkywardSwordFile::SkywardSwordFile() : m_numQuests(0) {}
: m_numQuests(0)
{ SkywardSwordFile::SkywardSwordFile(std::vector<SkywardSwordQuest*> quests) : m_numQuests(0) { m_quests = quests; }
SkywardSwordFile::~SkywardSwordFile() {}
void SkywardSwordFile::addQuest(athena::SkywardSwordQuest* q) {
// Do not allow more than 3 quests
if (m_quests.size() >= 3)
return;
m_quests.push_back(q);
} }
SkywardSwordFile::SkywardSwordFile(std::vector<SkywardSwordQuest*> quests) SkywardSwordQuest* SkywardSwordFile::quest(atUint32 id) {
: m_numQuests(0) if (id > m_quests.size() - 1) {
{ atWarning("index out of range");
m_quests = quests; return nullptr;
}
return m_quests[id];
} }
SkywardSwordFile::~SkywardSwordFile() std::vector<SkywardSwordQuest*> SkywardSwordFile::questList() const { return m_quests; }
{
}
void SkywardSwordFile::addQuest(athena::SkywardSwordQuest* q) void SkywardSwordFile::setRegion(Region region) { m_region = region; }
{
// Do not allow more than 3 quests
if (m_quests.size() >= 3)
return;
m_quests.push_back(q); Region SkywardSwordFile::region() const { return m_region; }
}
SkywardSwordQuest* SkywardSwordFile::quest(atUint32 id) } // namespace athena
{
if (id > m_quests.size() - 1)
{
atWarning("index out of range");
return nullptr;
}
return m_quests[id];
}
std::vector<SkywardSwordQuest*> SkywardSwordFile::questList() const
{
return m_quests;
}
void SkywardSwordFile::setRegion(Region region)
{
m_region = region;
}
Region SkywardSwordFile::region() const
{
return m_region;
}
} // zelda

View File

@ -3,64 +3,56 @@
#include "athena/SkywardSwordQuest.hpp" #include "athena/SkywardSwordQuest.hpp"
#include <iostream> #include <iostream>
namespace athena::io namespace athena::io {
{
SkywardSwordFileReader::SkywardSwordFileReader(atUint8* data, atUint64 length) SkywardSwordFileReader::SkywardSwordFileReader(atUint8* data, atUint64 length) : MemoryCopyReader(data, length) {
: MemoryCopyReader(data, length) setEndian(Endian::Big);
{
setEndian(Endian::Big);
} }
SkywardSwordFileReader::SkywardSwordFileReader(const std::string& filename) SkywardSwordFileReader::SkywardSwordFileReader(const std::string& filename) : MemoryCopyReader(filename) {
: MemoryCopyReader(filename) setEndian(Endian::Big);
{
setEndian(Endian::Big);
} }
SkywardSwordFile* SkywardSwordFileReader::read() SkywardSwordFile* SkywardSwordFileReader::read() {
{ SkywardSwordFile* file = NULL;
SkywardSwordFile* file = NULL;
if (length() != 0xFBE0) if (length() != 0xFBE0) {
{ atError("File not the expected size of 0xFBE0");
atError("File not the expected size of 0xFBE0"); return nullptr;
return nullptr; }
}
atUint32 magic = readUint32(); atUint32 magic = readUint32();
if (magic != SkywardSwordFile::USMagic && magic != SkywardSwordFile::JAMagic && magic != SkywardSwordFile::EUMagic) if (magic != SkywardSwordFile::USMagic && magic != SkywardSwordFile::JAMagic && magic != SkywardSwordFile::EUMagic) {
{ atError("Not a valid Skyward Sword save file");
atError("Not a valid Skyward Sword save file"); return nullptr;
return nullptr; }
}
seek(0x01C, SeekOrigin::Begin); seek(0x01C, SeekOrigin::Begin);
atUint32 headerSize = readUint32(); // Seems to be (headerSize - 1) atUint32 headerSize = readUint32(); // Seems to be (headerSize - 1)
if (headerSize != 0x1D) if (headerSize != 0x1D) {
{ atError("Invalid header size, Corrupted data?");
atError("Invalid header size, Corrupted data?"); return nullptr;
return nullptr; }
}
// Time to read in each slot // Time to read in each slot
file = new SkywardSwordFile; file = new SkywardSwordFile;
file->setRegion((magic == SkywardSwordFile::USMagic ? Region::NTSC : (magic == SkywardSwordFile::JAMagic ? Region::NTSCJ : Region::PAL))); file->setRegion((magic == SkywardSwordFile::USMagic
? Region::NTSC
: (magic == SkywardSwordFile::JAMagic ? Region::NTSCJ : Region::PAL)));
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++) {
{ SkywardSwordQuest* q = new SkywardSwordQuest(readUBytes(0x53C0), 0x53C0);
SkywardSwordQuest* q = new SkywardSwordQuest(readUBytes(0x53C0), 0x53C0); atUint64 pos = position();
atUint64 pos = position(); // seek to the skip data for this particular quest
// seek to the skip data for this particular quest seek(0xFB60 + (i * 0x24), SeekOrigin::Begin);
seek(0xFB60 + (i * 0x24), SeekOrigin::Begin); q->setSkipData(readUBytes(0x24));
q->setSkipData(readUBytes(0x24)); seek(pos, SeekOrigin::Begin);
seek(pos, SeekOrigin::Begin); file->addQuest(q);
file->addQuest(q); }
}
return file; return file;
} }
} // zelda } // namespace athena::io

View File

@ -2,62 +2,54 @@
#include "athena/SkywardSwordFile.hpp" #include "athena/SkywardSwordFile.hpp"
#include "athena/SkywardSwordQuest.hpp" #include "athena/SkywardSwordQuest.hpp"
namespace athena::io namespace athena::io {
{
SkywardSwordFileWriter::SkywardSwordFileWriter(atUint8* data, atUint64 len) SkywardSwordFileWriter::SkywardSwordFileWriter(atUint8* data, atUint64 len) : MemoryCopyWriter(data, len) {
: MemoryCopyWriter(data, len) setEndian(Endian::Big);
{
setEndian(Endian::Big);
} }
SkywardSwordFileWriter::SkywardSwordFileWriter(const std::string& filename) SkywardSwordFileWriter::SkywardSwordFileWriter(const std::string& filename) : MemoryCopyWriter(filename) {
: MemoryCopyWriter(filename) setEndian(Endian::Big);
{
setEndian(Endian::Big);
} }
void SkywardSwordFileWriter::write(SkywardSwordFile* file) void SkywardSwordFileWriter::write(SkywardSwordFile* file) {
{ if (!file) {
if (!file) atError("file cannot be NULL");
{ return;
atError("file cannot be NULL"); }
return;
atUint32 magic = (file->region() == Region::NTSC
? SkywardSwordFile::USMagic
: (file->region() == Region::NTSCJ ? SkywardSwordFile::JAMagic : SkywardSwordFile::EUMagic));
writeUint32(magic);
seek(0x1C, SeekOrigin::Begin);
writeUint32(0x1D);
std::vector<SkywardSwordQuest*> quests = file->questList();
int i = 0;
for (SkywardSwordQuest* q : quests) {
if (q->length() != 0x53C0) {
atError("q->data() not 0x53C0 bytes in length");
return;
} }
atUint32 magic = (file->region() == Region::NTSC ? SkywardSwordFile::USMagic : // Update the checksums
(file->region() == Region::NTSCJ ? SkywardSwordFile::JAMagic : SkywardSwordFile::EUMagic)); q->fixChecksums();
// Write the save data
writeUBytes(q->data(), q->length());
atUint64 pos = position();
// Write the slots skip data
seek(0xFB60 + (i * 0x24), SeekOrigin::Begin);
writeUBytes(q->skipData(), 0x24);
seek(pos, SeekOrigin::Begin);
i++;
}
writeUint32(magic); // write those padding bytes
seek(0x1C, SeekOrigin::Begin); seek(0xFBE0, SeekOrigin::Begin);
writeUint32(0x1D); save();
std::vector<SkywardSwordQuest*> quests = file->questList();
int i = 0;
for (SkywardSwordQuest* q : quests)
{
if (q->length() != 0x53C0)
{
atError("q->data() not 0x53C0 bytes in length");
return;
}
// Update the checksums
q->fixChecksums();
// Write the save data
writeUBytes(q->data(), q->length());
atUint64 pos = position();
// Write the slots skip data
seek(0xFB60 + (i * 0x24), SeekOrigin::Begin);
writeUBytes(q->skipData(), 0x24);
seek(pos, SeekOrigin::Begin);
i++;
}
// write those padding bytes
seek(0xFBE0, SeekOrigin::Begin);
save();
} }
} // zelda } // namespace athena::io

Some files were not shown because too many files have changed in this diff Show More