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>
#endif
static void *xfb = nullptr;
static void* xfb = nullptr;
static GXRModeObj* rmode = nullptr;
#endif
#include <athena/MemoryReader.hpp>
int main()
{
int main() {
#if GEKKO
VIDEO_Init();
VIDEO_Init();
#if HW_RVL
WPAD_Init();
WPAD_Init();
#endif
PAD_Init();
PAD_Init();
rmode = VIDEO_GetPreferredMode(nullptr);
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
rmode = VIDEO_GetPreferredMode(nullptr);
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
CON_Init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ);
CON_EnableGecko(CARD_SLOTB, true);
CON_Init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ);
CON_EnableGecko(CARD_SLOTB, true);
VIDEO_Configure(rmode);
VIDEO_SetBlack(false);
VIDEO_Configure(rmode);
VIDEO_SetBlack(false);
VIDEO_Flush();
VIDEO_Flush();
VIDEO_WaitVSync();
if (rmode->viTVMode & VI_NON_INTERLACE)
VIDEO_WaitVSync();
if (rmode->viTVMode & VI_NON_INTERLACE)
VIDEO_WaitVSync();
athena::io::MemoryCopyReader test("sd:/test.dat");
while(true)
{
athena::io::MemoryCopyReader test("sd:/test.dat");
while (true) {
#if HW_RVL
WPAD_ScanPads();
WPAD_ScanPads();
#endif
PAD_ScanPads();
if (PAD_ButtonsDown(0) & PAD_BUTTON_START)
break;
PAD_ScanPads();
if (PAD_ButtonsDown(0) & PAD_BUTTON_START)
break;
#if HW_RVL
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
break;
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
break;
#endif
VIDEO_WaitVSync();
}
VIDEO_WaitVSync();
}
#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
int main(int argc, const char** argv)
{
TESTFile<atUint32, 2> file = {};
file.arrCount[0] = 2;
file.array.push_back(42);
file.array.push_back(64);
size_t binSize = 0;
file.binarySize(binSize);
athena::io::MemoryCopyWriter w(nullptr, binSize);
atInt64 pos = w.position();
file.write(w);
bool pass = !w.hasError() && w.position() - pos == binSize && binSize == EXPECTED_BYTES;
if (pass)
printf("[PASS] %" PRISize " bytes written\n", size_t(w.position() - pos));
else
printf("[FAIL] %" PRISize " bytes written; %" PRISize " bytes sized; %d bytes expected\n",
size_t(w.position() - pos), binSize, EXPECTED_BYTES);
return pass ? 0 : 1;
int main(int argc, const char** argv) {
TESTFile<atUint32, 2> file = {};
file.arrCount[0] = 2;
file.array.push_back(42);
file.array.push_back(64);
size_t binSize = 0;
file.binarySize(binSize);
athena::io::MemoryCopyWriter w(nullptr, binSize);
atInt64 pos = w.position();
file.write(w);
bool pass = !w.hasError() && w.position() - pos == binSize && binSize == EXPECTED_BYTES;
if (pass)
printf("[PASS] %" PRISize " bytes written\n", size_t(w.position() - pos));
else
printf("[FAIL] %" PRISize " bytes written; %" PRISize " bytes sized; %d bytes expected\n",
size_t(w.position() - pos), binSize, EXPECTED_BYTES);
return pass ? 0 : 1;
}

View File

@ -3,87 +3,71 @@
using namespace athena;
typedef io::DNA<Big> BigDNA;
enum ETest : atUint8
{
ZERO,
ONE,
TWO,
THREE
};
enum ETest : atUint8 { ZERO, ONE, TWO, THREE };
template <ETest EVal>
struct AT_SPECIALIZE_PARMS(ETest::ZERO, ETest::ONE, ETest::TWO, ETest::THREE)
TESTSubFile : public BigDNA
{
AT_DECL_DNA
Value<ETest> varE = EVal;
Value<atUint32> sub1;
Value<atUint32> sub2;
struct AT_SPECIALIZE_PARMS(ETest::ZERO, ETest::ONE, ETest::TWO, ETest::THREE) TESTSubFile : public BigDNA {
AT_DECL_DNA
Value<ETest> varE = EVal;
Value<atUint32> sub1;
Value<atUint32> sub2;
};
struct TESTSubClassFile : public TESTSubFile<ETest::ONE>
{
AT_DECL_DNA
Value<atUint32> sub3;
Value<atUint16> sub4;
struct TESTSubClassFile : public TESTSubFile<ETest::ONE> {
AT_DECL_DNA
Value<atUint32> sub3;
Value<atUint16> sub4;
};
struct TESTSubSubClassFile : public TESTSubClassFile
{
AT_DECL_DNA
Value<atUint32> sub5;
Value<atUint32> sub6;
struct TESTSubSubClassFile : public TESTSubClassFile {
AT_DECL_DNA
Value<atUint32> sub5;
Value<atUint32> sub6;
};
template <class Var32Tp, int Var32Val>
struct AT_SPECIALIZE_PARMS(atUint16, 42, atUint32, 87, atUint32, 2)
TESTFile : public BigDNA
{
struct AT_SPECIALIZE_PARMS(atUint16, 42, atUint32, 87, atUint32, 2) 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
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;
Value<atUint32> nestSub1;
Value<atUint32> nestSub2;
} nestedSubFile;
struct TESTNestedSubFile : public BigDNA
{
AT_DECL_DNA
Value<atUint32> nestSub1;
Value<atUint32> nestSub2;
} nestedSubFile;
using TESTSubFileUsing = TESTSubFile<ETest::TWO>;
TESTSubFileUsing subFile;
using TESTSubFileUsing = TESTSubFile<ETest::TWO>;
TESTSubFileUsing subFile;
Align<4> align;
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>
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;
Value<atUint32, Little> arrCount[2];
Vector<atUint32, AT_DNA_COUNT(arrCount[0])> array;
Value<atUint32, Little> arrCount[2];
Vector<atUint32, AT_DNA_COUNT(arrCount[0])> array;
Value<atUint32> arrAltCount;
Vector<atUint32, AT_DNA_COUNT(arrAltCount)> arrayAlt;
Value<atUint32> arrAltCount;
Vector<atUint32, AT_DNA_COUNT(arrAltCount)> arrayAlt;
Seek<21, Current> seek;
Seek<21, Current> seek;
Value<atUint32> arrCount2;
Vector<TESTSubFile<ETest::ZERO>, AT_DNA_COUNT(arrCount[1] + arrCount2)> array2;
Value<atUint32> arrCount2;
Vector<TESTSubFile<ETest::ZERO>, AT_DNA_COUNT(arrCount[1] + arrCount2)> array2;
Value<atUint32> bufSz;
Buffer<AT_DNA_COUNT(bufSz)> buf;
Value<atUint32> bufSz;
Buffer<AT_DNA_COUNT(bufSz)> buf;
String<32> str;
WString<64> wstr;
String<32> str;
WString<64> wstr;
};

View File

@ -3,40 +3,38 @@
#include <string>
#include "LZ77/LZLookupTable.hpp"
class LZBase
{
class LZBase {
public:
explicit LZBase(atInt32 minimumOffset = 1, atInt32 slidingWindow = 4096, atInt32 minimumMatch = 3, atInt32 blockSize = 8);
virtual ~LZBase() {}
explicit LZBase(atInt32 minimumOffset = 1, atInt32 slidingWindow = 4096, atInt32 minimumMatch = 3,
atInt32 blockSize = 8);
virtual ~LZBase() {}
virtual atUint32 compress(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();
virtual atUint32 compress(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();
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:
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;
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;
};

View File

@ -6,32 +6,25 @@
#include <cstdint>
#include <athena/Types.hpp>
struct LZLengthOffset
{
atUint32 length;//The number of bytes compressed
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;
}
struct LZLengthOffset {
atUint32 length; // The number of bytes compressed
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; }
};
class LZLookupTable
{
class LZLookupTable {
public:
LZLookupTable();
LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow = 4096, atInt32 lookAheadWindow = 18);
~LZLookupTable();
LZLengthOffset search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd);
void setLookAheadWindow(atInt32 lookAheadWindow);
LZLookupTable();
LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow = 4096, atInt32 lookAheadWindow = 18);
~LZLookupTable();
LZLengthOffset search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd);
void setLookAheadWindow(atInt32 lookAheadWindow);
private:
typedef std::multimap<std::vector<uint8_t>, int32_t> LookupTable;
LookupTable table;
atInt32 m_minimumMatch;
atInt32 m_slidingWindow;
atInt32 m_lookAheadWindow;
std::vector<uint8_t> m_buffer;
typedef std::multimap<std::vector<uint8_t>, int32_t> LookupTable;
LookupTable table;
atInt32 m_minimumMatch;
atInt32 m_slidingWindow;
atInt32 m_lookAheadWindow;
std::vector<uint8_t> m_buffer;
};

View File

@ -2,11 +2,10 @@
#include "LZBase.hpp"
class LZType10 : public LZBase
{
class LZType10 : public LZBase {
public:
explicit LZType10(atInt32 minimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3, atInt32 BlockSize = 8);
atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength);
atUint32 decompress(const atUint8* src, atUint8** dst, atUint32 srcLen);
explicit LZType10(atInt32 minimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3,
atInt32 BlockSize = 8);
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
#include "LZBase.hpp"
class LZType11 : public LZBase
{
class LZType11 : public LZBase {
public:
explicit LZType11(atInt32 MinimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3, atInt32 BlockSize = 8);
atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength);
atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength);
explicit LZType11(atInt32 MinimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3,
atInt32 BlockSize = 8);
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 <memory>
namespace athena
{
namespace athena {
class IAES
{
class IAES {
public:
virtual ~IAES() {}
virtual void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)=0;
virtual void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)=0;
virtual void setKey(const uint8_t* key)=0;
virtual ~IAES() {}
virtual void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len) = 0;
virtual void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len) = 0;
virtual void setKey(const uint8_t* key) = 0;
};
std::unique_ptr<IAES> NewAES();
}
} // namespace athena

View File

@ -2,92 +2,56 @@
#include "Types.hpp"
namespace athena
{
namespace athena {
enum BowType : char
{
BowNone,
BowArrows,
BowSilverArrows
enum BowType : char { BowNone, BowArrows, BowSilverArrows };
enum BoomerangType : char { BoomerangNone, BoomerangBlue, BoomerangRed };
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
{
BoomerangNone,
BoomerangBlue,
BoomerangRed
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 MagicType : char
{
MagicNone,
MagicMushroom,
MagicPowder
enum ALTTPTagAlong {
Noone,
Zelda,
Unknown1,
Oldman,
ZeldaMessage,
Blind,
DwarfFrog,
DwarfLW,
Kiki,
Unknown2,
TheifsChest,
AfterBoss
};
enum ArmorType : char
{
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
} // namespace athena

View File

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

View File

@ -5,12 +5,10 @@
#include "athena/MemoryReader.hpp"
#include "athena/ALTTPQuest.hpp"
namespace athena
{
namespace athena {
class ALTTPFile;
namespace io
{
namespace io {
/*! \class ALTTPFileReader
* \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.
* \sa BinaryReader
*/
class ALTTPFileReader : protected MemoryCopyReader
{
class ALTTPFileReader : protected MemoryCopyReader {
public:
/*! \brief This constructor takes an existing buffer to read from.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
ALTTPFileReader(atUint8*, atUint64);
/*! \brief This constructor takes an existing buffer to read from.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
ALTTPFileReader(atUint8*, atUint64);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
ALTTPFileReader(const std::string&);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
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:
ALTTPRoomFlags* readRoomFlags();
ALTTPOverworldEvent* readOverworldEvent();
ALTTPDungeonItemFlags readDungeonFlags();
ALTTPRoomFlags* readRoomFlags();
ALTTPOverworldEvent* readOverworldEvent();
ALTTPDungeonItemFlags readDungeonFlags();
};
} // io
} // zelda
} // namespace io
} // namespace athena

View File

@ -4,12 +4,10 @@
#include "athena/MemoryWriter.hpp"
#include "athena/ALTTPQuest.hpp"
namespace athena
{
namespace athena {
class ALTTPFile;
namespace io
{
namespace io {
/*! \class ALTTPFileWriter
* \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.
* \sa BinaryReader
*/
class ALTTPFileWriter : protected MemoryCopyWriter
{
class ALTTPFileWriter : protected MemoryCopyWriter {
public:
/*! \brief This constructor takes an existing buffer to write to.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
ALTTPFileWriter(atUint8*, atUint64);
/*! \brief This constructor takes an existing buffer to write to.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
ALTTPFileWriter(atUint8*, atUint64);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
ALTTPFileWriter(const std::string&);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
ALTTPFileWriter(const std::string&);
/*! \brief Writes the given SRAM data to a file on disk
*
* \param file SRAM data to right
*/
void writeFile(ALTTPFile* file);
/*! \brief Writes the given SRAM data to a file on disk
*
* \param file SRAM data to right
*/
void writeFile(ALTTPFile* file);
private:
void writeRoomFlags(ALTTPRoomFlags*);
void writeOverworldEvent(ALTTPOverworldEvent*);
void writeDungeonItems(ALTTPDungeonItemFlags);
atUint16 calculateChecksum(atUint32 game);
void writeRoomFlags(ALTTPRoomFlags*);
void writeOverworldEvent(ALTTPOverworldEvent*);
void writeDungeonItems(ALTTPDungeonItemFlags);
atUint16 calculateChecksum(atUint32 game);
};
} // io
} // zelda
} // namespace io
} // namespace athena

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -2,10 +2,10 @@
#include "athena/Global.hpp"
namespace athena::checksums
{
atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed = 0xFFFFFFFFFFFFFFFF, atUint64 final = 0xFFFFFFFFFFFFFFFF);
namespace athena::checksums {
atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed = 0xFFFFFFFFFFFFFFFF,
atUint64 final = 0xFFFFFFFFFFFFFFFF);
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 crc16(const atUint8* data, atUint64 length, atUint16 seed = 0, atUint16 final = 0);
}
} // namespace athena::checksums

View File

@ -2,196 +2,161 @@
#include <cstdint>
namespace athena::checksums::literals
{
namespace athena::checksums::literals {
constexpr uint32_t crc32_table[] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
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
constexpr uint32_t crc32_table[] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832,
0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A,
0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4,
0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76,
0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6,
0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7,
0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
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};
template <uint32_t CRC, char... Chars>
struct Crc32Impl {};
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...> {
static constexpr uint32_t value = Crc32Impl<
crc32_table[static_cast<unsigned char>(CRC) ^ static_cast<unsigned char>(Head)]
^ (CRC >> 8), Tail...>::value;
};
template <char... Chars>
using Crc32 = Crc32Impl<0xFFFFFFFF, Chars...>;
template<uint32_t CRC> struct Crc32Impl<CRC> {
static constexpr uint32_t value = CRC ^ 0xFFFFFFFF;
};
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 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) {
return crc32_rec(0xFFFFFFFF, s);
constexpr uint32_t operator"" _crc32(const char* s, size_t len) { 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,
"CRC32 values don't match");
static_assert("0"_crc32 == Crc32<'0'>::value,
"CRC32 values don't match");
constexpr uint32_t operator"" _rcrc32(const char* s, size_t len) { return rcrc32_rec(0xFFFFFFFF, s); }
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) {
return *s == 0 ? crc :
crc32_rec(crc32_table[static_cast<unsigned char>(crc) ^
static_cast<unsigned char>(*s)]
^ (crc >> 8), s + 1);
}
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};
constexpr uint32_t operator "" _rcrc32(const char *s, size_t len) {
return rcrc32_rec(0xFFFFFFFF, s);
}
template <uint64_t CRC, char... Chars>
struct Crc64Impl {};
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 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 Head, char... Tail>
struct Crc64Impl<CRC, Head, Tail...> {
static constexpr uint64_t value =
Crc64Impl<crc64_table[static_cast<unsigned char>(CRC >> 56) ^ static_cast<unsigned char>(Head)] ^ (CRC << 8),
Tail...>::value;
};
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...> {
static constexpr uint64_t value = Crc64Impl<
crc64_table[static_cast<unsigned char>(CRC >> 56) ^ static_cast<unsigned char>(Head)]
^ (CRC << 8), Tail...>::value;
};
template <char... Chars>
using Crc64 = Crc64Impl<0xFFFFFFFFFFFFFFFF, Chars...>;
template<uint64_t CRC> struct Crc64Impl<CRC> {
static constexpr uint64_t value = CRC ^ 0xFFFFFFFFFFFFFFFF;
};
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 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) {
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");
}
constexpr uint64_t operator"" _crc64(const char* s, size_t len) { 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");
} // namespace athena::checksums::literals

View File

@ -2,8 +2,7 @@
#include "athena/Global.hpp"
namespace athena::io::Compression
{
namespace athena::io::Compression {
// Zlib compression
atInt32 decompressZlib(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 compressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst, bool extended = false);
}
} // namespace athena::io::Compression

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -8,30 +8,26 @@
typedef int mode_t;
#endif
namespace athena
{
class Dir
{
namespace athena {
class Dir {
public:
explicit Dir(std::string_view path);
explicit Dir(std::string_view path);
std::string absolutePath() const;
static inline std::string absolutePath(std::string_view path)
{ return Dir(path).absolutePath(); }
std::string absolutePath() const;
static inline std::string absolutePath(std::string_view path) { return Dir(path).absolutePath(); }
bool isDir() const;
static bool isDir(std::string_view dir)
{ return Dir(dir).isDir(); }
bool isDir() const;
static bool isDir(std::string_view dir) { 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:
std::string m_path;
std::string m_path;
};
}
} // namespace athena

View File

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

View File

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

View File

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

View File

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

View File

@ -2,31 +2,30 @@
#include "Global.hpp"
namespace athena::io
{
namespace athena::io {
std::ostream& operator<<(std::ostream& os, Endian& endian);
class IStream
{
class IStream {
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:
void setError() { m_hasError = true; }
bool m_hasError = false;
void setError() { m_hasError = true; }
bool m_hasError = false;
#if __BYTE_ORDER == __BIG_ENDIAN
Endian m_endian = Big;
Endian m_endian = Big;
#else
Endian m_endian = Little;
Endian m_endian = Little;
#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"
namespace athena
{
namespace athena {
class MCSlot;
/*! \class MCFile
@ -12,23 +11,18 @@ class MCSlot;
* Contains all relevant data for a The Minish Cap save,
* file.
*/
class MCFile
{
class MCFile {
public:
static const char VERSION_EU_JP[33];
static const char VERSION_US[33];
enum SlotType
{
New = 0x54494E49,
Valid = 0x4D435A33,
Deleted = 0x466C6544
};
static const char VERSION_EU_JP[33];
static const char VERSION_US[33];
enum SlotType { New = 0x54494E49, Valid = 0x4D435A33, Deleted = 0x466C6544 };
MCFile();
MCFile();
static atUint8* unscramble(atUint8* data, atUint64 length);
static atUint8* unscramble(atUint8* data, atUint64 length);
private:
MCSlot* m_slots[3];
MCSlot* m_slots[3];
};
} // zelda
} // namespace athena

View File

@ -2,13 +2,11 @@
#include "athena/MemoryReader.hpp"
namespace athena
{
namespace athena {
class MCFile;
namespace io
{
namespace io {
/*! \class MCFileReader
* \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.
* \sa BinaryReader
*/
class MCFileReader : public MemoryCopyReader
{
class MCFileReader : public MemoryCopyReader {
public:
/*!
* \brief This constructor takes an existing buffer to read from.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
MCFileReader(atUint8*, atUint64);
/*!
* \brief This constructor takes an existing buffer to read from.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
MCFileReader(atUint8*, atUint64);
/*!
* \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
MCFileReader(const std::string&);
/*!
* \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
MCFileReader(const std::string&);
/*!
* \brief Reads the save data from the buffer
*
* \return MCFile* SRAM data
*/
MCFile* readFile();
/*!
* \brief Reads the save data from the buffer
*
* \return MCFile* SRAM data
*/
MCFile* readFile();
};
} // io
} // zelda
} // namespace io
} // namespace athena

View File

@ -3,13 +3,11 @@
#include "athena/Types.hpp"
#include "athena/MemoryWriter.hpp"
namespace athena
{
namespace athena {
class MCFile;
namespace io
{
namespace io {
/*! \class MCFileWriter
* \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.
* \sa BinaryWriter
*/
class MCFileWriter : protected MemoryCopyWriter
{
class MCFileWriter : protected MemoryCopyWriter {
public:
/*!
* \brief This constructor takes an existing buffer to write to.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
MCFileWriter(atUint8*, atUint64);
/*!
* \brief This constructor takes an existing buffer to write to.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
MCFileWriter(atUint8*, atUint64);
/*!
* \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
MCFileWriter(const std::string&);
/*!
* \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
MCFileWriter(const std::string&);
/*!
* \brief Writes the given save data to a file on disk
*
* \param file Save data to write
*/
void writeFile(MCFile* file);
/*!
* \brief Writes the given save data to a file on disk
*
* \param file Save data to write
*/
void writeFile(MCFile* file);
static atUint16 calculateChecksum(atUint8* data, atUint32 length);
static atUint16 calculateChecksum(atUint8* data, atUint32 length);
private:
atUint16 calculateSlotChecksum(atUint32 game);
atUint16 calculateSlotChecksum(atUint32 game);
};
} // io
} // zelda
} // namespace io
} // namespace athena

View File

@ -3,13 +3,10 @@
#include "athena/Global.hpp"
#include "athena/ZQuestFile.hpp"
namespace athena
{
class MCSlot : public ZQuestFile
{
namespace athena {
class MCSlot : public ZQuestFile {
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 "athena/IStreamReader.hpp"
namespace athena::io
{
namespace athena::io {
/*! \class MemoryReader
* \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
* \sa Stream
*/
class MemoryReader : public IStreamReader
{
class MemoryReader : public IStreamReader {
protected:
MemoryReader() = default;
MemoryReader() = default;
public:
virtual ~MemoryReader();
virtual ~MemoryReader();
/*! \brief This constructor references an existing buffer to read from.
*
* \param data The existing buffer
* \param length The length of the existing buffer
* \param takeOwnership Memory will be freed with the reader if set
*/
MemoryReader(const void* data, atUint64 length, bool takeOwnership=false, bool globalErr=true);
/*! \brief This constructor references an existing buffer to read from.
*
* \param data The existing buffer
* \param length The length of the existing buffer
* \param takeOwnership Memory will be freed with the reader if set
*/
MemoryReader(const void* data, atUint64 length, bool takeOwnership = false, bool globalErr = true);
/*! \brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default.
* \param position where in the buffer to seek
* \param origin The Origin to seek \sa SeekOrigin
*/
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! \brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default.
* \param position where in the buffer to seek
* \param origin The Origin to seek \sa SeekOrigin
*/
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! \brief Returns the current position in the stream.
*
* \return Int64 The current position in the stream.
*/
inline atUint64 position() const
{return m_position;}
/*! \brief Returns the current position in the stream.
*
* \return Int64 The current position in the stream.
*/
inline atUint64 position() const { return m_position; }
/*! \brief Returns whether or not the stream is at the end.
*
* \return bool True if at end; False otherwise.
*/
inline atUint64 length() const
{return m_length;}
/*! \brief Returns whether or not the stream is at the end.
*
* \return bool True if at end; False otherwise.
*/
inline atUint64 length() const { 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 />
* <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 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 />
* 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.
* \return Uint8* The copy of the buffer.
*/
atUint8* data() const;
/*! \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 />
* 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.
* \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);
/*! \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:
const void* m_data = nullptr;
atUint64 m_length = 0;
atUint64 m_position = 0;
bool m_owns = false;
bool m_globalErr = true;
const void* m_data = nullptr;
atUint64 m_length = 0;
atUint64 m_position = 0;
bool m_owns = false;
bool m_globalErr = true;
};
class MemoryCopyReader : public MemoryReader
{
class MemoryCopyReader : public MemoryReader {
public:
/*! \brief This constructor copies an existing buffer to read from.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
MemoryCopyReader(const void* data, atUint64 length);
/*! \brief This constructor copies an existing buffer to read from.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
MemoryCopyReader(const void* data, atUint64 length);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
MemoryCopyReader(const std::string& filename)
: m_filepath(filename)
{loadData();}
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
MemoryCopyReader(const std::string& filename) : m_filepath(filename) { loadData(); }
void setData(const atUint8* data, atUint64 length);
void setData(const atUint8* data, atUint64 length);
protected:
void loadData();
std::unique_ptr<atUint8[]> m_dataCopy;
std::string m_filepath; //!< Path to the target file
void loadData();
std::unique_ptr<atUint8[]> m_dataCopy;
std::string m_filepath; //!< Path to the target file
};
} // Athena
} // namespace athena::io

View File

@ -5,8 +5,7 @@
#include <functional>
#include "athena/IStreamWriter.hpp"
namespace athena::io
{
namespace athena::io {
/*! @class MemoryWriter
* @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
* @sa Stream
*/
class MemoryWriter : public IStreamWriter
{
class MemoryWriter : public IStreamWriter {
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.
*
* @param data The existing buffer
* @param length The length of the existing buffer
*/
explicit MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership = false);
/*! @brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default.
* @param position where in the buffer to seek
* @param origin The Origin to seek @sa SeekOrigin
*/
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! @brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default.
* @param position where in the buffer to seek
* @param origin The Origin to seek @sa SeekOrigin
*/
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! @brief Returns the current position in the stream.
*
* @return Int64 The current position in the stream.
*/
inline atUint64 position() const { return m_position; }
/*! @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.
*
* @return Int64 The current position in the stream.
*/
inline atUint64 position() const
{return m_position;}
inline bool isOpen() const { return true; }
/*! @brief Returns the length of the stream.
*
* @return Int64 The length of the stream.
*/
inline atUint64 length() const
{return m_length;}
/** @brief Sets the buffer to the given one, deleting the current one if it owns it.<br />
* @param data The new buffer.
* @param length The length of the new buffer.
* @param takeOwnership Whether the Stream now owns the buffer.
*/
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 />
* @param data The new buffer.
* @param length The length of the new buffer.
* @param takeOwnership Whether the Stream now owns the buffer.
*/
void setData(atUint8* data, atUint64 length, bool takeOwnership = false);
/*! @brief Sets the target file
*
* @param filepath The path to write to.
*/
inline void setFilepath(const std::string& filepath) { m_filepath = filepath; }
/*! @brief
* Returns the target file
*/
inline std::string filepath() const { return m_filepath; }
/*! @brief 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 Saves the file to the specified file.
*
* @param filename If not empty, the filename to save to
*/
void save(std::string_view filename = {});
/*! @brief Sets the target file
*
* @param filepath The path to write to.
*/
inline void setFilepath(const std::string& filepath)
{m_filepath = filepath;}
/*! @brief
* Returns the target file
*/
inline std::string filepath() const
{return m_filepath;}
/*! @brief 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);
/*! @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:
MemoryWriter() {}
atUint8* m_data;
atUint64 m_length;
atUint64 m_position;
bool m_bufferOwned;
std::string m_filepath; //!< Path to the target file
MemoryWriter() {}
atUint8* m_data;
atUint64 m_length;
atUint64 m_position;
bool m_bufferOwned;
std::string m_filepath; //!< Path to the target file
};
class MemoryCopyWriter : public MemoryWriter
{
class MemoryCopyWriter : public MemoryWriter {
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.
*
* @param data The existing buffer
* @param length The length of the existing buffer
*/
explicit MemoryCopyWriter(atUint8* data=nullptr, atUint64 length=0x10);
/*! @brief This constructor creates an instance from a file on disk.
*
* @param filename The file to create the stream from
*/
MemoryCopyWriter(std::string_view filename);
/*! @brief This constructor creates an instance from a file on disk.
*
* @param filename The file to create the stream from
*/
MemoryCopyWriter(std::string_view filename);
/*! @brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default.
* @param position where in the buffer to seek
* @param origin The Origin to seek @sa SeekOrigin
*/
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! @brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default.
* @param position where in the buffer to seek
* @param origin The Origin to seek @sa SeekOrigin
*/
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! @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.
* @throw IOException
*/
void setData(const atUint8* data, atUint64 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.
* @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);
/*! @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:
std::unique_ptr<atUint8[]> m_dataCopy;
std::unique_ptr<atUint8[]> m_dataCopy;
private:
void resize(atUint64 newSize);
void resize(atUint64 newSize);
};
}
} // namespace athena::io

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,89 +14,71 @@ typedef UINT_PTR SOCKET;
struct sockaddr_in;
namespace athena::net
{
namespace athena::net {
/** IP address class derived from SFML */
class IPAddress
{
uint32_t m_address = 0;
bool m_valid = false;
class IPAddress {
uint32_t m_address = 0;
bool m_valid = false;
void resolve(const std::string& address);
void resolve(const std::string& address);
public:
IPAddress(const std::string& address)
{
resolve(address);
}
IPAddress(const std::string& address) { resolve(address); }
uint32_t toInteger() const;
operator bool() const { return m_valid; }
uint32_t toInteger() const;
operator bool() const { return m_valid; }
};
/** Server-oriented TCP socket class derived from SFML */
class Socket
{
class Socket {
#ifndef _WIN32
using SocketTp = int;
using SocketTp = int;
#else
using SocketTp = SOCKET;
using SocketTp = SOCKET;
#endif
SocketTp m_socket = -1;
bool m_isBlocking;
SocketTp m_socket = -1;
bool m_isBlocking;
bool openSocket();
void setRemoteSocket(int remSocket);
bool openSocket();
void setRemoteSocket(int remSocket);
public:
enum class EResult
{
OK,
Error,
Busy
};
enum class EResult { OK, Error, Busy };
#ifdef _WIN32
static EResult LastWSAError();
static EResult LastWSAError();
#endif
Socket(bool blocking)
: m_isBlocking(blocking) {}
~Socket() { close(); }
Socket(bool blocking) : m_isBlocking(blocking) {}
~Socket() { close(); }
Socket(const Socket& other) = delete;
Socket& operator=(const Socket& other) = delete;
Socket(Socket&& other)
: m_socket(other.m_socket), m_isBlocking(other.m_isBlocking)
{
other.m_socket = -1;
}
Socket& operator=(Socket&& other)
{
close();
m_socket = other.m_socket;
other.m_socket = -1;
m_isBlocking = other.m_isBlocking;
return *this;
}
Socket(const Socket& other) = delete;
Socket& operator=(const Socket& other) = delete;
Socket(Socket&& other) : m_socket(other.m_socket), m_isBlocking(other.m_isBlocking) { other.m_socket = -1; }
Socket& operator=(Socket&& other) {
close();
m_socket = other.m_socket;
other.m_socket = -1;
m_isBlocking = other.m_isBlocking;
return *this;
}
void setBlocking(bool blocking);
bool isOpen() const { return m_socket != -1; }
bool openAndListen(const IPAddress& address, uint32_t port);
EResult accept(Socket& remoteSocketOut, sockaddr_in& fromAddress);
EResult accept(Socket& remoteSocketOut);
EResult accept(Socket& remoteSocketOut, std::string& fromHostname);
void close();
EResult send(const void* buf, size_t len, size_t& transferred);
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);
void setBlocking(bool blocking);
bool isOpen() const { return m_socket != -1; }
bool openAndListen(const IPAddress& address, uint32_t port);
EResult accept(Socket& remoteSocketOut, sockaddr_in& fromAddress);
EResult accept(Socket& remoteSocketOut);
EResult accept(Socket& remoteSocketOut, std::string& fromHostname);
void close();
EResult send(const void* buf, size_t len, size_t& transferred);
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);
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 "athena/SakuraGlobal.hpp"
namespace athena::Sakura
{
namespace athena::Sakura {
class SpriteFile;
class SpriteFrame;
class Sprite
{
class Sprite {
public:
Sprite(SpriteFile* root);
Sprite(SpriteFile* root, const std::string& name);
virtual ~Sprite();
Sprite(SpriteFile* root);
Sprite(SpriteFile* root, const std::string& name);
virtual ~Sprite();
virtual void setPosition(const float x, const float y);
virtual void setPosition(const Vector2Df& pos);
virtual Vector2Df position() const;
void setName(const std::string& name);
std::string name() const;
virtual void setPosition(const float x, const float y);
virtual void setPosition(const Vector2Df& pos);
virtual Vector2Df position() const;
void setName(const std::string& name);
std::string name() const;
void addStateId(int id);
void addStateId(int id);
/*!
* \brief Returns the texture id of a given state
* \param index The index of the id.
* \return return the state id if it exists, -1 otherwise
*/
int stateId(int index) const;
void setStateIds(std::vector<int> ids);
std::vector<int> stateIds() const;
atUint32 stateCount() const;
void setCurrentState(atUint32 id);
atUint32 currentState() const;
/*!
* \brief Returns the texture id of a given state
* \param index The index of the id.
* \return return the state id if it exists, -1 otherwise
*/
int stateId(int index) const;
void setStateIds(std::vector<int> ids);
std::vector<int> stateIds() const;
atUint32 stateCount() const;
void setCurrentState(atUint32 id);
atUint32 currentState() const;
bool addFrame(SpriteFrame* Frame);
bool removeFrame(SpriteFrame* Frame);
SpriteFrame* Frame(atUint32 id);
void setFrame(atUint32 id);
void setFrames(std::vector<SpriteFrame*> frames);
atUint32 frameCount() const;
bool addFrame(SpriteFrame* Frame);
bool removeFrame(SpriteFrame* Frame);
SpriteFrame* Frame(atUint32 id);
void setFrame(atUint32 id);
void setFrames(std::vector<SpriteFrame*> frames);
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(atUint32 id);
SpriteFrame* currentFrame() const;
void setCurrentFrame(SpriteFrame* frame);
void setCurrentFrame(atUint32 id);
SpriteFrame* currentFrame() const;
void advanceFrame();
void retreatFrame();
void advanceFrame();
void retreatFrame();
void setRoot(SpriteFile* root);
SpriteFile* root() const;
void setRoot(SpriteFile* root);
SpriteFile* root() const;
private:
SpriteFile* m_root;
std::string m_name;
Vector2Df m_position;
std::vector<int> m_stateIds; //!< Stores the texture id's for each state.
std::vector<SpriteFrame*> m_frames;
atUint32 m_currentState;
atUint32 m_currentFrame;
SpriteFile* m_root;
std::string m_name;
Vector2Df m_position;
std::vector<int> m_stateIds; //!< Stores the texture id's for each state.
std::vector<SpriteFrame*> m_frames;
atUint32 m_currentState;
atUint32 m_currentFrame;
};
} // zelda
} // namespace athena::Sakura

View File

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

View File

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

View File

@ -2,25 +2,21 @@
#include "athena/MemoryWriter.hpp"
namespace athena
{
namespace Sakura
{
namespace athena {
namespace Sakura {
class SpriteFile;
} // Sakura
} // namespace Sakura
namespace io
{
namespace io {
class SpriteFileWriter : public MemoryCopyWriter
{
class SpriteFileWriter : public MemoryCopyWriter {
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
} // zelda
} // namespace io
} // namespace athena

View File

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

View File

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

View File

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

View File

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

View File

@ -6,8 +6,7 @@
#include <vector>
#include "athena/IStreamWriter.hpp"
namespace athena::io
{
namespace athena::io {
/*! @class VectorWriter
* @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
* @sa Stream
*/
class VectorWriter : public IStreamWriter
{
class VectorWriter : public IStreamWriter {
public:
/*! @brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default.
* @param position where in the buffer to seek
* @param origin The Origin to seek @sa SeekOrigin
*/
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! @brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default.
* @param position where in the buffer to seek
* @param origin The Origin to seek @sa SeekOrigin
*/
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
/*! @brief Returns the current position in the stream.
*
* @return Int64 The current position in the stream.
*/
inline atUint64 position() const { return m_position; }
/*! @brief Returns the current position in the stream.
*
* @return Int64 The current position in the stream.
*/
inline atUint64 position() const { return m_position; }
/*! @brief Returns the length of the stream.
*
* @return Int64 The length of the stream.
*/
inline atUint64 length() const { return m_data.size(); }
/*! @brief Returns the length of the stream.
*
* @return Int64 The length of the stream.
*/
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 */
const std::vector<uint8_t>& data() const { return m_data; }
/*! @brief Obtains reference to underlying std::vector store */
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
* 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);
/*! @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:
std::vector<uint8_t> m_data;
atUint64 m_position = 0;
std::vector<uint8_t> m_data;
atUint64 m_position = 0;
};
}
} // namespace athena::io

View File

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

View File

@ -5,217 +5,213 @@
#include <vector>
#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_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};
const atUint8 SD_KEY[16] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08,
0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d};
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
* \brief Wii file container class
*
* Contains all relevant data for a file in a data.bin file.
*/
class WiiFile
{
class WiiFile {
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
* \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,
// Mask values;
OtherRW = (OtherRead | OtherWrite), //!< Mask to get the Other group permissions
GroupRW = (GroupRead | GroupWrite),
OwnerRW = (OwnerRead | OwnerWrite)
};
// Mask values;
OtherRW = (OtherRead | OtherWrite), //!< Mask to get the Other group permissions
GroupRW = (GroupRead | GroupWrite),
OwnerRW = (OwnerRead | OwnerWrite)
};
/*!
* \brief The Type enum
*/
enum Type { File = 0x01, Directory = 0x02 };
/*!
* \brief The Type enum
*/
enum Type
{
File = 0x01,
Directory = 0x02
};
WiiFile();
WiiFile();
/*!
* \brief WiiFile
* \param filename
*/
WiiFile(const std::string& filename);
/*!
* \brief WiiFile
* \param filename
*/
WiiFile(const std::string& filename);
/*!
* \brief WiiFile
* \param filename
* \param permissions
* \param data
* \param length
*/
WiiFile(const std::string& filename, atUint8 permissions, const atUint8* data, atUint32 length);
virtual ~WiiFile();
/*!
* \brief WiiFile
* \param filename
* \param permissions
* \param data
* \param length
*/
WiiFile(const std::string& filename, atUint8 permissions, const atUint8* data, atUint32 length);
virtual ~WiiFile();
/*!
* \brief setFilename
* \param filename
*/
void setFilename(const std::string& filename);
/*!
* \brief setFilename
* \param filename
*/
void setFilename(const std::string& filename);
/*!
* \brief filename
* \return
*/
std::string filename() const;
/*!
* \brief filename
* \return
*/
std::string filename() const;
/*!
* \brief setData
* \param data
*/
void setData(const atUint8* data);
/*!
* \brief data
* \return
*/
atUint8* data() const;
/*!
* \brief setData
* \param data
*/
void setData(const atUint8* data);
/*!
* \brief data
* \return
*/
atUint8* data() const;
/*!
* \brief setLength
* \param len
*/
void setLength(const int len);
/*!
* \brief setLength
* \param len
*/
void setLength(const int len);
/*!
* \brief length
* \return
*/
int length() const;
/*!
* \brief length
* \return
*/
int length() const;
/*!
* \brief setPermissions
* \param permissions
*/
void setPermissions(const atUint8 permissions);
/*!
* \brief setPermissions
* \param permissions
*/
void setPermissions(const atUint8 permissions);
/*!
* \brief permissions
* \return
*/
atUint8 permissions() const;
/*!
* \brief permissions
* \return
*/
atUint8 permissions() const;
/*!
* \brief setAttributes
* \param attr
*/
void setAttributes(const atUint8 attr);
/*!
* \brief setAttributes
* \param attr
*/
void setAttributes(const atUint8 attr);
/*!
* \brief attributes
* \return
*/
atUint8 attributes() const;
/*!
* \brief attributes
* \return
*/
atUint8 attributes() const;
/*!
* \brief setType
* \param type
*/
void setType(Type type);
/*!
* \brief setType
* \param type
*/
void setType(Type type);
/*!
* \brief type
* \return
*/
Type type() const;
/*!
* \brief type
* \return
*/
Type type() const;
/*!
* \brief isDirectory
* \return
*/
bool isDirectory() const;
/*!
* \brief isDirectory
* \return
*/
bool isDirectory() const;
/*!
* \brief isFile
* \return
*/
bool isFile() const;
/*!
* \brief isFile
* \return
*/
bool isFile() const;
/*!
* \brief addChild
* \param file
*/
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
* \param file
*/
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 parent
* \return
*/
WiiFile* parent();
/*!
* \brief parent
* \return
*/
WiiFile* parent();
/*!
* \brief setParent
* \param parent
*/
void setParent(WiiFile* parent);
/*!
* \brief setParent
* \param parent
*/
void setParent(WiiFile* parent);
/*!
* \brief fileCount
* \return
*/
atUint32 fileCount();
/*!
* \brief fileCount
* \return
*/
atUint32 fileCount();
/*!
* \brief allChildren
* \return
*/
std::vector<WiiFile*> allChildren();
/*!
* \brief allChildren
* \return
*/
std::vector<WiiFile*> allChildren();
/*!
* \brief fullpath
* \return
*/
std::string fullpath();
/*!
* \brief fullpath
* \return
*/
std::string fullpath();
protected:
private:
atUint8 m_permissions;
atUint8 m_attributes;
Type m_type;
std::string m_filename;
int m_fileLen;
atUint8* m_fileData;
WiiFile* m_parent;
std::vector<WiiFile*> m_children;
atUint8 m_permissions;
atUint8 m_attributes;
Type m_type;
std::string m_filename;
int m_fileLen;
atUint8* m_fileData;
WiiFile* m_parent;
std::vector<WiiFile*> m_children;
};
} // zelda
} // namespace athena

View File

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

View File

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

View File

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

View File

@ -2,15 +2,13 @@
#include "athena/MemoryWriter.hpp"
namespace athena
{
namespace athena {
class WiiSave;
class WiiBanner;
class WiiFile;
class WiiImage;
namespace io
{
namespace io {
/*! \class WiiSaveWriter
* \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.
* \sa BinaryReader
*/
class WiiSaveWriter : protected MemoryCopyWriter
{
class WiiSaveWriter : protected MemoryCopyWriter {
public:
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
WiiSaveWriter(const std::string&);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
WiiSaveWriter(const std::string&);
/*!
* \brief writeSave
* \param save
* \param macAddress
* \param ngId
* \param ngPriv
* \param ngSig
* \param ngKeyId
* \param filepath
* \return
*/
bool writeSave(WiiSave* save, atUint8* macAddress, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId, const std::string& filepath = "");
/*!
* \brief writeSave
* \param save
* \param macAddress
* \param ngId
* \param ngPriv
* \param ngSig
* \param ngKeyId
* \param filepath
* \return
*/
bool writeSave(WiiSave* save, atUint8* macAddress, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId,
const std::string& filepath = "");
private:
void writeBanner(WiiBanner* banner);
atUint32 writeFile(WiiFile* file);
void writeImage(WiiImage* image);
void writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId);
void writeBanner(WiiBanner* banner);
atUint32 writeFile(WiiFile* file);
void writeImage(WiiImage* image);
void writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId);
};
} // io
} // zelda
} // namespace io
} // namespace athena

View File

@ -12,157 +12,147 @@
#include <functional>
#include "Global.hpp"
namespace athena::io
{
namespace athena::io {
class IStreamReader;
class IStreamWriter;
enum class YAMLNodeStyle
{
Any,
Flow,
Block
enum class YAMLNodeStyle { Any, Flow, Block };
struct YAMLNode {
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));
}
};
struct YAMLNode
{
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>
template <typename RETURNTYPE>
RETURNTYPE NodeToVal(const YAMLNode* node);
template<>
template <>
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);
std::unique_ptr <YAMLNode> ValToNode(atInt8 val);
std::unique_ptr<YAMLNode> ValToNode(atInt8 val);
template<>
template <>
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);
std::unique_ptr <YAMLNode> ValToNode(atInt16 val);
std::unique_ptr<YAMLNode> ValToNode(atInt16 val);
template<>
template <>
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);
std::unique_ptr <YAMLNode> ValToNode(atInt32 val);
std::unique_ptr<YAMLNode> ValToNode(atInt32 val);
template<>
template <>
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);
std::unique_ptr <YAMLNode> ValToNode(atInt64 val);
std::unique_ptr<YAMLNode> ValToNode(atInt64 val);
template<>
template <>
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);
std::unique_ptr <YAMLNode> ValToNode(float val);
std::unique_ptr<YAMLNode> ValToNode(float val);
template<>
template <>
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);
template<>
template <>
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);
std::unique_ptr <YAMLNode> ValToNode(const atVec3f& val);
std::unique_ptr<YAMLNode> ValToNode(const atVec3f& val);
template<>
template <>
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);
std::unique_ptr <YAMLNode> ValToNode(const atVec2d& val);
std::unique_ptr<YAMLNode> ValToNode(const atVec2d& val);
template<>
template <>
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);
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 <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::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::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);
@ -172,28 +162,22 @@ void HandleYAMLParserError(yaml_parser_t* parser);
void HandleYAMLEmitterError(yaml_emitter_t* emitter);
struct YAMLStdStringViewReaderState
{
std::string_view::const_iterator begin;
std::string_view::const_iterator end;
struct YAMLStdStringViewReaderState {
std::string_view::const_iterator begin;
std::string_view::const_iterator end;
YAMLStdStringViewReaderState(std::string_view str)
{
begin = str.begin();
end = str.end();
}
YAMLStdStringViewReaderState(std::string_view str) {
begin = str.begin();
end = str.end();
}
};
int YAMLStdStringReader(YAMLStdStringViewReaderState* str,
unsigned char* buffer, size_t size, size_t* size_read);
int YAMLStdStringReader(YAMLStdStringViewReaderState* str, unsigned char* buffer, size_t size, size_t* size_read);
int YAMLStdStringWriter(std::string* str, unsigned char* buffer, size_t size);
int YAMLAthenaReader(athena::io::IStreamReader* reader,
unsigned char* buffer, size_t size, size_t* size_read);
int YAMLAthenaReader(athena::io::IStreamReader* reader, unsigned char* buffer, size_t size, size_t* size_read);
int YAMLAthenaWriter(athena::io::IStreamWriter* writer,
unsigned char* buffer, size_t size);
}
int YAMLAthenaWriter(athena::io::IStreamWriter* writer, unsigned char* buffer, size_t size);
} // namespace athena::io

View File

@ -2,168 +2,160 @@
#include "YAMLCommon.hpp"
namespace athena::io
{
namespace athena::io {
class YAMLDocReader
{
std::unique_ptr<YAMLNode> m_rootNode;
std::vector<YAMLNode*> m_subStack;
std::vector<int> m_seqTrackerStack;
yaml_parser_t m_parser;
std::unique_ptr<YAMLNode> ParseEvents(athena::io::IStreamReader* reader);
void _leaveSubRecord();
void _leaveSubVector();
class YAMLDocReader {
std::unique_ptr<YAMLNode> m_rootNode;
std::vector<YAMLNode*> m_subStack;
std::vector<int> m_seqTrackerStack;
yaml_parser_t m_parser;
std::unique_ptr<YAMLNode> ParseEvents(athena::io::IStreamReader* reader);
void _leaveSubRecord();
void _leaveSubVector();
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 ValidateClassType(const char* expectedType);
bool ClassTypeOperation(std::function<bool(const char* dnaType)> func);
bool ValidateClassType(const char* expectedType);
inline const YAMLNode* getRootNode() const { return m_rootNode.get(); }
inline const YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); }
std::unique_ptr<YAMLNode> releaseRootNode() { return std::move(m_rootNode); }
inline const YAMLNode* getRootNode() const { return m_rootNode.get(); }
inline const YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); }
std::unique_ptr<YAMLNode> releaseRootNode() { return std::move(m_rootNode); }
class RecordRAII
{
friend class YAMLDocReader;
YAMLDocReader* m_r = nullptr;
RecordRAII(YAMLDocReader* r) : m_r(r) {}
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;
class RecordRAII {
friend class YAMLDocReader;
YAMLDocReader* m_r = nullptr;
RecordRAII(YAMLDocReader* r) : m_r(r) {}
RecordRAII() = default;
RecordRAII enterSubRecord(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.read(*this);
public:
operator bool() const { return m_r != nullptr; }
void leave() {
if (m_r) {
m_r->_leaveSubRecord();
m_r = nullptr;
}
}
class VectorRAII
{
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;
~RecordRAII() {
if (m_r)
m_r->_leaveSubRecord();
}
};
friend class RecordRAII;
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.push_back(readVal<T>(name));
}
return countOut;
RecordRAII enterSubRecord(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.read(*this);
}
class VectorRAII {
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;
template <class T>
size_t enumerate(const char* name, std::vector<T>& vector,
std::function<void(YAMLDocReader&, T&)> readf)
{
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))
readf(*this, vector.back());
}
}
return countOut;
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;
}
bool hasVal(const char* name) const
{
if (m_subStack.size())
{
const YAMLNode* mnode = m_subStack.back();
if (mnode->m_type == YAML_MAPPING_NODE && name)
for (const auto& item : mnode->m_mapChildren)
if (!item.first.compare(name))
return true;
}
return false;
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.push_back(readVal<T>(name));
}
return countOut;
}
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);
template <class T>
size_t enumerate(const char* name, std::vector<T>& vector, std::function<void(YAMLDocReader&, T&)> readf) {
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))
readf(*this, vector.back());
}
}
return countOut;
}
bool hasVal(const char* name) const {
if (m_subStack.size()) {
const YAMLNode* mnode = m_subStack.back();
if (mnode->m_type == YAML_MAPPING_NODE && name)
for (const auto& item : mnode->m_mapChildren)
if (!item.first.compare(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"
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:
YAMLDocWriter(const char* classType, athena::io::IStreamReader* reader = nullptr);
~YAMLDocWriter();
YAMLDocWriter(const char* classType, athena::io::IStreamReader* reader = nullptr);
~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
{
friend class YAMLDocWriter;
YAMLDocWriter* m_w = nullptr;
RecordRAII(YAMLDocWriter* w) : m_w(w) {}
RecordRAII() = default;
public:
operator bool() const { return m_w != nullptr; }
~RecordRAII() { if (m_w) m_w->_leaveSubRecord(); }
};
friend class RecordRAII;
class RecordRAII {
friend class YAMLDocWriter;
YAMLDocWriter* m_w = nullptr;
RecordRAII(YAMLDocWriter* w) : m_w(w) {}
RecordRAII() = default;
RecordRAII enterSubRecord(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);
public:
operator bool() const { return m_w != nullptr; }
~RecordRAII() {
if (m_w)
m_w->_leaveSubRecord();
}
};
friend class RecordRAII;
class VectorRAII
{
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;
RecordRAII enterSubRecord(const char* name);
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>
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 (const T& item : vector)
if (auto rec = enterSubRecord(nullptr))
item.write(*this);
class VectorRAII {
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;
template <class T>
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);
}
VectorRAII enterSubVector(const char* name);
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 <class T>
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 (const T& item : vector)
if (auto rec = enterSubRecord(nullptr))
item.write(*this);
}
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);
template <class T>
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);
}
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
#define ZQUEST_HPP
#include "athena/Global.hpp"
#include <string>
#include <vector>
#include <memory>
#define ZQUEST_VERSION_CHECK(major, minor, revision) \
(major | (minor << 8) | (revision << 16))
#define ZQUEST_VERSION_CHECK(major, minor, revision) (major | (minor << 8) | (revision << 16))
namespace athena
{
namespace athena {
/*!
* \brief ZQuestFile is an export format for save data.
*/
class ZQuestFile
{
class ZQuestFile {
public:
/*!
* \brief The current major version of the ZQuest format
*/
static const atUint32 Major;
/*!
* \brief The current minor version of the ZQuest format
*/
static const atUint32 Minor;
/*!
* \brief The current revision of the ZQuest format
*/
static const atUint32 Revision;
/*!
* \brief The current version of the ZQuest format
*/
static const atUint32 Version;
/*!
* \brief The current major version of the ZQuest format
*/
static const atUint32 Major;
/*!
* \brief The current minor version of the ZQuest format
*/
static const atUint32 Minor;
/*!
* \brief The current revision of the ZQuest format
*/
static const atUint32 Revision;
/*!
* \brief The current version of the ZQuest format
*/
static const atUint32 Version;
/*!
* \brief The magic number used to identify the file e.g. "ZQS1"
*/
static const atUint32 Magic;
/*!
* \brief The magic number used to identify the file e.g. "ZQS1"
*/
static const atUint32 Magic;
/*!
* \enum Game
* \brief The list of games currently supported by ZQuest
*/
enum Game
{
NoGame, //!< None or Unsupported
LoZ, //!< Legend of Zelda
AoL, //!< Adventure of Link
ALttP, //!< A Link to the Past
LA, //!< Links Awakening
OoT, //!< Ocarin of Time
OoT3D, //!< Ocarina of Time 3D
MM, //!< Majora's Mask
OoS, //!< Oracle of Season
OoA, //!< Oracle of Ages
FS, //!< Four Swords
WW, //!< Wind Waker
FSA, //!< Four Swords Adventures
MC, //!< Minish Cap
TP, //!< Twilight Princess
PH, //!< Phantom Hourglass
ST, //!< Spirit Tracks
SS, //!< Skyward Sword
ALBW, //!< A Link Between Worlds
// Add more games here
/*!
* \enum Game
* \brief The list of games currently supported by ZQuest
*/
enum Game {
NoGame, //!< None or Unsupported
LoZ, //!< Legend of Zelda
AoL, //!< Adventure of Link
ALttP, //!< A Link to the Past
LA, //!< Links Awakening
OoT, //!< Ocarin of Time
OoT3D, //!< Ocarina of Time 3D
MM, //!< Majora's Mask
OoS, //!< Oracle of Season
OoA, //!< Oracle of Ages
FS, //!< Four Swords
WW, //!< Wind Waker
FSA, //!< Four Swords Adventures
MC, //!< Minish Cap
TP, //!< Twilight Princess
PH, //!< Phantom Hourglass
ST, //!< Spirit Tracks
SS, //!< Skyward Sword
ALBW, //!< A Link Between Worlds
// Add more games here
// This must always be last
GameCount //!< Total number of supported games
};
// This must always be last
GameCount //!< Total number of supported games
};
/*!
* \brief ZQuest
*/
ZQuestFile();
/*!
* \brief ZQuest
*/
ZQuestFile();
/*!
* \brief ZQuest
* \param game
* \param endian
* \param data
* \param length
*/
ZQuestFile(Game game, Endian endian, std::unique_ptr<atUint8[]>&& data, atUint32 length, const std::string& gameString = std::string());
/*!
* \brief ZQuest
* \param game
* \param endian
* \param data
* \param length
*/
ZQuestFile(Game game, Endian endian, std::unique_ptr<atUint8[]>&& data, atUint32 length,
const std::string& gameString = std::string());
/*!
* \brief setGame
* \param game
*/
void setGame(Game game);
/*!
* \brief setGame
* \param game
*/
void setGame(Game game);
/*!
* \brief game
* \return
*/
Game game() const;
/*!
* \brief game
* \return
*/
Game game() const;
/*!
* \brief setEndian
* \param endian
*/
void setEndian(Endian endian);
/*!
* \brief setEndian
* \param endian
*/
void setEndian(Endian endian);
/*!
* \brief endian
* \return
*/
Endian endian() const;
/*!
* \brief endian
* \return
*/
Endian endian() const;
/*!
* \brief setData
* \param data The data to assign
* \param length The length of the data
*/
void setData(std::unique_ptr<atUint8[]>&& data, atUint32 length);
/*!
* \brief setData
* \param data The data to assign
* \param length The length of the data
*/
void setData(std::unique_ptr<atUint8[]>&& data, atUint32 length);
/*!
* \brief data
* \return
*/
atUint8* data() const;
/*!
* \brief data
* \return
*/
atUint8* data() const;
/*!
* \brief length
* \return
*/
atUint32 length() const;
/*!
* \brief length
* \return
*/
atUint32 length() const;
void setGameString(const std::string& gameString);
/*!
* \brief gameString
* \return
*/
std::string gameString() const;
void setGameString(const std::string& gameString);
/*!
* \brief gameString
* \return
*/
std::string gameString() const;
static const std::vector<std::string> gameStringList();
static const std::vector<std::string> gameStringList();
protected:
Game m_game;
std::string m_gameString;
Endian m_endian;
std::unique_ptr<atUint8[]> m_data;
atUint32 m_length;
Game m_game;
std::string m_gameString;
Endian m_endian;
std::unique_ptr<atUint8[]> m_data;
atUint32 m_length;
// Game strings support
// Game strings support
};
} // zelda
} // namespace athena
#endif // ZQUEST_HPP
#endif // ATHENA_NO_ZQUEST

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,13 +1,11 @@
#pragma once
#include "athena/Types.hpp"
namespace bignum
{
namespace bignum {
int compare(const atUint8* a, const atUint8* b, 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 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 inv(atUint8* d, atUint8* a, const atUint8* N, atUint32 n);
}
} // namespace bignum

View File

@ -1,11 +1,8 @@
#pragma once
#include "athena/Types.hpp"
namespace ecc
{
namespace ecc {
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 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/LZBase.hpp"
LZBase::LZBase(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize)
: m_slidingWindow(slidingWindow),
m_readAheadBuffer(minimumMatch),
m_minMatch(minimumMatch),
m_blockSize(blockSize),
m_minOffset(minimumOffset)
{
}
: m_slidingWindow(slidingWindow)
, m_readAheadBuffer(minimumMatch)
, m_minMatch(minimumMatch)
, m_blockSize(blockSize)
, m_minOffset(minimumOffset) {}
void LZBase::setSlidingWindow(atInt32 slidingWindow)
{
m_slidingWindow = slidingWindow;
}
void LZBase::setSlidingWindow(atInt32 slidingWindow) { m_slidingWindow = slidingWindow; }
atInt32 LZBase::slidingWindow() {return m_slidingWindow;}
atInt32 LZBase::slidingWindow() { return m_slidingWindow; }
void LZBase::setReadAheadBuffer(atInt32 readAheadBuffer)
{
m_readAheadBuffer = readAheadBuffer;
}
void LZBase::setReadAheadBuffer(atInt32 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)
{
m_blockSize = blockSize ;
}
void LZBase::setBlockSize(atInt32 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()
{
return m_minOffset;
}
atUint32 LZBase::minimumOffset() { return m_minOffset; }
/*
DerricMc:
@ -54,55 +39,51 @@ atUint32 LZBase::minimumOffset()
and 17 bytes did match then 17 bytes match is return).
*/
LZLengthOffset LZBase::search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd)
{
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);
LZLengthOffset LZBase::search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd) {
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);
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 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;
return len;
}
/*
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
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
the number of bytes that did match before it failed to match. The submatch is function returns the number of bytes that
were equal, which can result up to the bytes total length if both byte strings are equal.
equal the function return the next best match(which means if the function look for 18 bytes and they are not found,
return the number of bytes that did match before it failed to match. The submatch is function returns the number of
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
Up to 4114 bytes
*/
LZLengthOffset LZBase::windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr, atUint8* startLBPtr)
{
atInt32 size = (atUint32)(endLABufferPtr - beginSearchPtr); //Size of the entire sliding window
atInt32 n = (atUint32)(endLABufferPtr - searchPosPtr);
LZLengthOffset result = {0, 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);
LZLengthOffset LZBase::windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr,
atUint8* startLBPtr) {
atInt32 size = (atUint32)(endLABufferPtr - beginSearchPtr); // Size of the entire sliding window
atInt32 n = (atUint32)(endLABufferPtr - searchPosPtr);
LZLengthOffset result = {0, 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);
return result;
}

View File

@ -1,129 +1,116 @@
#include "LZ77/LZLookupTable.hpp"
#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;
if (slidingWindow > 0)
m_slidingWindow = slidingWindow;
else
m_slidingWindow = 4096;
if (lookAheadWindow > 0)
m_lookAheadWindow = lookAheadWindow;
else
m_lookAheadWindow = 18;
m_buffer.resize(m_minimumMatch);
m_buffer.reserve(m_minimumMatch);
}
LZLookupTable::LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow, atInt32 lookAheadWindow)
{
if (minimumMatch > 0)
m_minimumMatch = minimumMatch;
else
m_minimumMatch = 3;
LZLookupTable::~LZLookupTable() {}
if (slidingWindow > 0)
m_slidingWindow = slidingWindow;
else
m_slidingWindow = 4096;
if (lookAheadWindow > 0)
m_lookAheadWindow = lookAheadWindow;
else
m_lookAheadWindow = 18;
m_buffer.reserve(m_minimumMatch);
void LZLookupTable::setLookAheadWindow(atInt32 lookAheadWindow) {
if (lookAheadWindow > 0)
m_lookAheadWindow = lookAheadWindow;
else
m_lookAheadWindow = 18;
}
LZLookupTable::~LZLookupTable()
{}
LZLengthOffset LZLookupTable::search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd) {
LZLengthOffset loPair = {0, 0};
void LZLookupTable::setLookAheadWindow(atInt32 lookAheadWindow)
{
if (lookAheadWindow > 0)
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
// 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;
//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>
LZType10::LZType10(atInt32 MinimumOffset, atInt32 SlidingWindow, atInt32 MinimumMatch, atInt32 BlockSize)
: LZBase(MinimumOffset, SlidingWindow, MinimumMatch, BlockSize)
{
//ReadAheadBuffer is normalize between (minumum match) and(minimum match + 15) so that matches fit within
//4-bits.
m_readAheadBuffer = m_minMatch + 0xF;
: LZBase(MinimumOffset, SlidingWindow, MinimumMatch, BlockSize) {
// ReadAheadBuffer is normalize between (minumum match) and(minimum match + 15) so that matches fit within
// 4-bits.
m_readAheadBuffer = m_minMatch + 0xF;
}
atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLength)
{
atUint32 encodeSize = (srcLength << 8) | (0x10);
encodeSize = athena::utility::LittleUint32(encodeSize); //File size needs to be written as little endian always
atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLength) {
atUint32 encodeSize = (srcLength << 8) | (0x10);
encodeSize = athena::utility::LittleUint32(encodeSize); // File size needs to be written as little endian always
athena::io::MemoryCopyWriter outbuf("tmp");
outbuf.writeUint32(encodeSize);
athena::io::MemoryCopyWriter outbuf("tmp");
outbuf.writeUint32(encodeSize);
atUint8* ptrStart = (atUint8*)src;
atUint8* ptrEnd = (atUint8*)(src + srcLength);
atUint8* ptrStart = (atUint8*)src;
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
atUint8* compressedBytes = new atUint8[m_blockSize * 2]; //Holds the compressed bytes yet to be written
// 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
atUint8* compressedBytes = new atUint8[m_blockSize * 2]; // Holds the compressed bytes yet to be written
while (ptrStart < ptrEnd)
{
atUint8 blockLen = 0;
//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
atUint8* ptrBytes = compressedBytes;
while (ptrStart < ptrEnd) {
atUint8 blockLen = 0;
// 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
atUint8* ptrBytes = compressedBytes;
for (atInt32 i = 0; i < m_blockSize; i++)
{
//length_offset searchResult=Search(ptrStart, filedata, ptrEnd);
LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd);
for (atInt32 i = 0; i < m_blockSize; i++) {
// length_offset searchResult=Search(ptrStart, filedata, 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 (searchResult.length >= (atUint32)m_minMatch)
{
//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);
athena::utility::BigUint16(lenOff);
// If the number of bytes to be compressed is at least the size of the Minimum match
if (searchResult.length >= (atUint32)m_minMatch) {
// 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);
athena::utility::BigUint16(lenOff);
memcpy(ptrBytes, &lenOff, sizeof(atUint16));
memcpy(ptrBytes, &lenOff, sizeof(atUint16));
ptrBytes += sizeof(atUint16);
ptrBytes += sizeof(atUint16);
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));
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++;
}
delete[] compressedBytes;
compressedBytes = nullptr;
outbuf.writeByte(blockLen);
outbuf.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes));
}
//Add zeros until the file is a multiple of 4
while ((outbuf.position() % 4) != 0)
outbuf.writeByte(0);
delete[] compressedBytes;
compressedBytes = nullptr;
*dstBuf = outbuf.data();
outbuf.save();
return (atUint32)outbuf.length();
// Add zeros until the file is a multiple of 4
while ((outbuf.position() % 4) != 0)
outbuf.writeByte(0);
*dstBuf = outbuf.data();
outbuf.save();
return (atUint32)outbuf.length();
}
atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength)
{
if (*(atUint8*)(src) != 0x10)
return 0;
atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
if (*(atUint8*)(src) != 0x10)
return 0;
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
uncompressedSize = uncompressedSize >> 8;//first byte is the encode flag
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
uncompressedSize = uncompressedSize >> 8; // first byte is the encode flag
atUint8* uncompressedData = new atUint8[uncompressedSize];
atUint8* outputPtr = uncompressedData;
atUint8* outputEndPtr = uncompressedData + uncompressedSize;
atUint8* inputPtr = (atUint8*)src + 4;
atUint8* inputEndPtr = (atUint8*)src + srcLength;
atUint8* uncompressedData = new atUint8[uncompressedSize];
atUint8* outputPtr = uncompressedData;
atUint8* outputEndPtr = uncompressedData + uncompressedSize;
atUint8* inputPtr = (atUint8*)src + 4;
atUint8* inputEndPtr = (atUint8*)src + srcLength;
while (inputPtr < inputEndPtr && outputPtr < outputEndPtr)
{
while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) {
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;
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;
}
}
*dst = uncompressedData;
*dst = uncompressedData;
return uncompressedSize;
return uncompressedSize;
}

View File

@ -3,233 +3,209 @@
#include <athena/MemoryWriter.hpp>
#include <cstring>
LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize)
: LZBase(minimumOffset, slidingWindow, minimumMatch, blockSize)
{
m_readAheadBuffer = (0xF + 0xFF + 0xFFFF + m_minMatch);
m_lookupTable.setLookAheadWindow(m_readAheadBuffer);
: LZBase(minimumOffset, slidingWindow, minimumMatch, blockSize) {
m_readAheadBuffer = (0xF + 0xFF + 0xFFFF + m_minMatch);
m_lookupTable.setLookAheadWindow(m_readAheadBuffer);
}
atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLength)
{
athena::io::MemoryCopyWriter outbuff("tmp");
atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
athena::io::MemoryCopyWriter outbuff("tmp");
if (srcLength > 0xFFFFFF) // If length is greater than 24 bits or 16 Megs
{
atUint32 encodeFlag = 0x11;
athena::utility::LittleUint32(encodeFlag);
athena::utility::LittleUint32(srcLength);//Filesize data is little endian
outbuff.writeUint32(encodeFlag);
outbuff.writeUint32(srcLength);
if (srcLength > 0xFFFFFF) // If length is greater than 24 bits or 16 Megs
{
atUint32 encodeFlag = 0x11;
athena::utility::LittleUint32(encodeFlag);
athena::utility::LittleUint32(srcLength); // Filesize data is little endian
outbuff.writeUint32(encodeFlag);
outbuff.writeUint32(srcLength);
}
else
{
atUint32 encodeSize = (srcLength << 8) | (0x11);
athena::utility::LittleUint32(encodeSize);
outbuff.writeUint32(encodeSize);
}
} else {
atUint32 encodeSize = (srcLength << 8) | (0x11);
athena::utility::LittleUint32(encodeSize);
outbuff.writeUint32(encodeSize);
}
atUint8* ptrStart = (atUint8*)src;
atUint8* ptrEnd = (atUint8*)(src + srcLength);
atUint8* ptrStart = (atUint8*)src;
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
atUint8* compressedBytes = new atUint8[m_blockSize * 2]; //Holds the compressed bytes yet to be written
// 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
atUint8* compressedBytes = new atUint8[m_blockSize * 2]; // Holds the compressed bytes yet to be written
atUint8 maxTwoByteMatch = 0xF + 1;
atUint8 minThreeByteMatch = maxTwoByteMatch + 1; //Minimum Three byte match is maximum TwoByte match + 1
atUint16 maxThreeByteMatch = 0xFF + minThreeByteMatch;
atUint16 minFourByteMatch = maxThreeByteMatch + 1; //Minimum Four byte match is maximum Three Byte match + 1
atInt32 maxFourByteMatch = 0xFFFF + minFourByteMatch;
atUint8 maxTwoByteMatch = 0xF + 1;
atUint8 minThreeByteMatch = maxTwoByteMatch + 1; // Minimum Three byte match is maximum TwoByte match + 1
atUint16 maxThreeByteMatch = 0xFF + minThreeByteMatch;
atUint16 minFourByteMatch = maxThreeByteMatch + 1; // Minimum Four byte match is maximum Three Byte match + 1
atInt32 maxFourByteMatch = 0xFFFF + minFourByteMatch;
/*
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
273 gets mapped to 0 and 65808 gets mapped to 65535
/*
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
273 gets mapped to 0 and 65808 gets mapped to 65535
A two byte match uses 4 bits
A three byte match uses 8 bits
A four byte match uses 16 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 three byte case the first 4 bits are 0000
In the four byte case the first 4 bits a 0001
*/
while (ptrStart < ptrEnd)
{
atUint8 blockSize = 0;
//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
atUint8* ptrBytes = compressedBytes;
A two byte match uses 4 bits
A three byte match uses 8 bits
A four byte match uses 16 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 three byte case the first 4 bits are 0000
In the four byte case the first 4 bits a 0001
*/
while (ptrStart < ptrEnd) {
atUint8 blockSize = 0;
// 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
atUint8* ptrBytes = compressedBytes;
for (atInt32 i = 0; i < m_blockSize; i++)
{
//length_offset searchResult=Search(filedata,ptrStart,ptrEnd);
LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd);
for (atInt32 i = 0; i < m_blockSize; i++) {
// length_offset searchResult=Search(filedata,ptrStart,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 (searchResult.length >= (atUint32)m_minMatch)
{
//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 the number of bytes to be compressed is at least the size of the Minimum match
if (searchResult.length >= (atUint32)m_minMatch) {
// 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;
}
outbuff.writeByte(blockSize);
outbuff.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes));
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++;
}
delete []compressedBytes;
compressedBytes = NULL;
outbuff.writeByte(blockSize);
outbuff.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes));
}
//Add zeros until the file is a multiple of 4
while ((outbuff.position() % 4) != 0)
outbuff.writeByte(0);
delete[] compressedBytes;
compressedBytes = NULL;
*dst = outbuff.data();
return (atUint32)outbuff.length();
// Add zeros until the file is a multiple of 4
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)
{
if (*(atUint8*)(src) != 0x11)
return 0;
atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
if (*(atUint8*)(src) != 0x11)
return 0;
atUint32 uncompressedLen = *(atUint32*)(src);
athena::utility::LittleUint32(uncompressedLen);//The compressed file has the filesize encoded in little endian
uncompressedLen = uncompressedLen >> 8; //First byte is the encode flag
atUint32 currentOffset = 4;
atUint32 uncompressedLen = *(atUint32*)(src);
athena::utility::LittleUint32(uncompressedLen); // The compressed file has the filesize encoded in little endian
uncompressedLen = uncompressedLen >> 8; // First byte is the encode flag
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
{
atUint32 filesize = *(atUint32*)(src + 4);
filesize = athena::utility::LittleUint32(filesize);
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
{
atUint32 filesize = *(atUint32*)(src + 4);
filesize = athena::utility::LittleUint32(filesize);
currentOffset += 4;
}
atUint8* uncompressedData = new atUint8[uncompressedLen];
atUint8* outputPtr = uncompressedData;
atUint8* outputEndPtr = uncompressedData + uncompressedLen;
atUint8* inputPtr = (atUint8*)src + currentOffset;
atUint8* inputEndPtr = (atUint8*)src + srcLength;
atUint8* uncompressedData = new atUint8[uncompressedLen];
atUint8* outputPtr = uncompressedData;
atUint8* outputEndPtr = uncompressedData + uncompressedLen;
atUint8* inputPtr = (atUint8*)src + currentOffset;
atUint8* inputEndPtr = (atUint8*)src + srcLength;
LZLengthOffset decoding;
atUint8 maxTwoByteMatch = 0xF + 1;
atUint8 threeByteDenorm = maxTwoByteMatch + 1; //Amount to add to length when compression is 3 bytes
atUint16 maxThreeByteMatch = 0xFF + threeByteDenorm;
atUint16 fourByteDenorm = maxThreeByteMatch + 1;
LZLengthOffset decoding;
atUint8 maxTwoByteMatch = 0xF + 1;
atUint8 threeByteDenorm = maxTwoByteMatch + 1; // Amount to add to length when compression is 3 bytes
atUint16 maxThreeByteMatch = 0xFF + threeByteDenorm;
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
//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
{
atUint16 lenOff = 0;
memcpy(&lenOff, inputPtr, 2);
inputPtr += 2;
athena::utility::BigUint16(lenOff);
decoding.length = (lenOff >> 12) + 1;
decoding.offset = (lenOff & 0xFFF) + 1;
}
else if (metaDataSize == 0) //Three Bytes of Length/Offset MetaData
{
atUint32 lenOff = 0;
memcpy((atUint8*)&lenOff + 1, inputPtr, 3);
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;
atUint16 lenOff = 0;
memcpy(&lenOff, inputPtr, 2);
inputPtr += 2;
athena::utility::BigUint16(lenOff);
decoding.length = (lenOff >> 12) + 1;
decoding.offset = (lenOff & 0xFFF) + 1;
} else if (metaDataSize == 0) // Three Bytes of Length/Offset MetaData
{
atUint32 lenOff = 0;
memcpy((atUint8*)&lenOff + 1, inputPtr, 3);
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;
}
}
*dst = uncompressedData;
return uncompressedLen;
*dst = uncompressedData;
return uncompressedLen;
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -4,233 +4,215 @@
#include <iostream>
#include "athena/Global.hpp"
namespace athena::io
{
namespace athena::io {
ALTTPFileReader::ALTTPFileReader(atUint8* data, atUint64 length)
: MemoryCopyReader(data, length)
{
}
ALTTPFileReader::ALTTPFileReader(atUint8* data, atUint64 length) : MemoryCopyReader(data, length) {}
ALTTPFileReader::ALTTPFileReader(const std::string& filename)
: MemoryCopyReader(filename)
{
}
ALTTPFileReader::ALTTPFileReader(const std::string& filename) : MemoryCopyReader(filename) {}
ALTTPFile* ALTTPFileReader::readFile()
{
std::vector<ALTTPQuest*> quests;
std::vector<ALTTPQuest*> backup;
ALTTPFile* ALTTPFileReader::readFile() {
std::vector<ALTTPQuest*> quests;
std::vector<ALTTPQuest*> backup;
for (atUint32 i = 0; i < 6; i++)
{
// Temporary values to use for each save
ALTTPQuest* quest = new ALTTPQuest();
std::vector<ALTTPRoomFlags*> roomFlags;
std::vector<ALTTPOverworldEvent*> owEvents;
std::vector<atUint8> dungeonKeys;
std::vector<atUint8> oldmanFlags;
std::vector<atUint8> unknown1;
std::vector<atUint16> playerName;
std::vector<atUint16> dungeonDeaths;
for (atUint32 i = 0; i < 6; i++) {
// Temporary values to use for each save
ALTTPQuest* quest = new ALTTPQuest();
std::vector<ALTTPRoomFlags*> roomFlags;
std::vector<ALTTPOverworldEvent*> owEvents;
std::vector<atUint8> dungeonKeys;
std::vector<atUint8> oldmanFlags;
std::vector<atUint8> unknown1;
std::vector<atUint16> playerName;
std::vector<atUint16> dungeonDeaths;
int j = 0x140;
int j = 0x140;
while ((j--) > 0)
{
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);
while ((j--) > 0) {
roomFlags.push_back(readRoomFlags());
}
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* flags = new ALTTPRoomFlags;
atUint8 flagsByte = readUByte();
flags->Chest1 = flagsByte & 1;
flags->Chest2 = (flagsByte >> 1) & 1;
flags->Chest3 = (flagsByte >> 2) & 1;
flags->Chest4 = (flagsByte >> 3) & 1;
flags->Quadrant1 = (flagsByte >> 4) & 1;
flags->Quadrant2 = (flagsByte >> 5) & 1;
flags->Quadrant3 = (flagsByte >> 6) & 1;
flags->Quadrant4 = (flagsByte >> 7) & 1;
flagsByte = readUByte();
flags->Door1 = flagsByte & 1;
flags->Door2 = (flagsByte >> 1) & 1;
flags->Door3 = (flagsByte >> 2) & 1;
flags->Door4 = (flagsByte >> 3) & 1;
flags->BossBattleWon = (flagsByte >> 4) & 1;
flags->Key = (flagsByte >> 5) & 1;
flags->KeyOrChest = (flagsByte >> 6) & 1;
flags->ChestOrTile = (flagsByte >> 7) & 1;
ALTTPRoomFlags* ALTTPFileReader::readRoomFlags() {
ALTTPRoomFlags* flags = new ALTTPRoomFlags;
atUint8 flagsByte = readUByte();
flags->Chest1 = flagsByte & 1;
flags->Chest2 = (flagsByte >> 1) & 1;
flags->Chest3 = (flagsByte >> 2) & 1;
flags->Chest4 = (flagsByte >> 3) & 1;
flags->Quadrant1 = (flagsByte >> 4) & 1;
flags->Quadrant2 = (flagsByte >> 5) & 1;
flags->Quadrant3 = (flagsByte >> 6) & 1;
flags->Quadrant4 = (flagsByte >> 7) & 1;
flagsByte = readUByte();
flags->Door1 = flagsByte & 1;
flags->Door2 = (flagsByte >> 1) & 1;
flags->Door3 = (flagsByte >> 2) & 1;
flags->Door4 = (flagsByte >> 3) & 1;
flags->BossBattleWon = (flagsByte >> 4) & 1;
flags->Key = (flagsByte >> 5) & 1;
flags->KeyOrChest = (flagsByte >> 6) & 1;
flags->ChestOrTile = (flagsByte >> 7) & 1;
return flags;
return flags;
}
ALTTPOverworldEvent* ALTTPFileReader::readOverworldEvent()
{
ALTTPOverworldEvent* event = new ALTTPOverworldEvent;
atUint8 flagsByte = readUByte();
event->Unused1 = flagsByte & 1;
event->HeartPiece = (flagsByte >> 1) & 1;
event->Overlay = (flagsByte >> 2) & 1;
event->Unused2 = (flagsByte >> 3) & 1;
event->Unused3 = (flagsByte >> 4) & 1;
event->Unused4 = (flagsByte >> 5) & 1;
event->Set = (flagsByte >> 6) & 1;
event->Unused5 = (flagsByte >> 7) & 1;
return event;
ALTTPOverworldEvent* ALTTPFileReader::readOverworldEvent() {
ALTTPOverworldEvent* event = new ALTTPOverworldEvent;
atUint8 flagsByte = readUByte();
event->Unused1 = flagsByte & 1;
event->HeartPiece = (flagsByte >> 1) & 1;
event->Overlay = (flagsByte >> 2) & 1;
event->Unused2 = (flagsByte >> 3) & 1;
event->Unused3 = (flagsByte >> 4) & 1;
event->Unused4 = (flagsByte >> 5) & 1;
event->Set = (flagsByte >> 6) & 1;
event->Unused5 = (flagsByte >> 7) & 1;
return event;
}
ALTTPDungeonItemFlags ALTTPFileReader::readDungeonFlags()
{
ALTTPDungeonItemFlags flags;
atUint8 flagsByte = readUByte();
flags.Unused1 = flagsByte & 1;
flags.Unused2 = (flagsByte >> 1) & 1;
flags.GanonsTower = (flagsByte >> 2) & 1;
flags.TurtleRock = (flagsByte >> 3) & 1;
flags.GargoylesDomain = (flagsByte >> 4) & 1;
flags.TowerOfHera = (flagsByte >> 5) & 1;
flags.IcePalace = (flagsByte >> 6) & 1;
flags.SkullWoods = (flagsByte >> 7) & 1;
flagsByte = readUByte();
flags.MiseryMire = flagsByte & 1;
flags.DarkPalace = (flagsByte >> 1) & 1;
flags.SwampPalace = (flagsByte >> 2) & 1;
flags.HyruleCastle2 = (flagsByte >> 3) & 1;
flags.DesertPalace = (flagsByte >> 4) & 1;
flags.EasternPalace = (flagsByte >> 5) & 1;
flags.HyruleCastle = (flagsByte >> 6) & 1;
flags.SewerPassage = (flagsByte >> 7) & 1;
ALTTPDungeonItemFlags ALTTPFileReader::readDungeonFlags() {
ALTTPDungeonItemFlags flags;
atUint8 flagsByte = readUByte();
flags.Unused1 = flagsByte & 1;
flags.Unused2 = (flagsByte >> 1) & 1;
flags.GanonsTower = (flagsByte >> 2) & 1;
flags.TurtleRock = (flagsByte >> 3) & 1;
flags.GargoylesDomain = (flagsByte >> 4) & 1;
flags.TowerOfHera = (flagsByte >> 5) & 1;
flags.IcePalace = (flagsByte >> 6) & 1;
flags.SkullWoods = (flagsByte >> 7) & 1;
flagsByte = readUByte();
flags.MiseryMire = flagsByte & 1;
flags.DarkPalace = (flagsByte >> 1) & 1;
flags.SwampPalace = (flagsByte >> 2) & 1;
flags.HyruleCastle2 = (flagsByte >> 3) & 1;
flags.DesertPalace = (flagsByte >> 4) & 1;
flags.EasternPalace = (flagsByte >> 5) & 1;
flags.HyruleCastle = (flagsByte >> 6) & 1;
flags.SewerPassage = (flagsByte >> 7) & 1;
atDebug("%x %x", flags.flags1, flags.flags2);
return flags;
atDebug("%x %x", flags.flags1, flags.flags2);
return flags;
}
} // io
} // namespace athena::io

View File

@ -3,221 +3,204 @@
#include "athena/ALTTPQuest.hpp"
#include <iostream>
namespace athena
{
namespace athena {
namespace io
{
namespace io {
ALTTPFileWriter::ALTTPFileWriter(atUint8* data, atUint64 length)
: MemoryCopyWriter(data, length)
{
}
ALTTPFileWriter::ALTTPFileWriter(atUint8* data, atUint64 length) : MemoryCopyWriter(data, length) {}
ALTTPFileWriter::ALTTPFileWriter(const std::string& filename)
: MemoryCopyWriter(filename)
{
}
ALTTPFileWriter::ALTTPFileWriter(const std::string& filename) : MemoryCopyWriter(filename) {}
void ALTTPFileWriter::writeFile(ALTTPFile* file)
{
ALTTPQuest* quest = NULL;
void ALTTPFileWriter::writeFile(ALTTPFile* file) {
ALTTPQuest* quest = NULL;
for (atUint32 i = 0; i < 6; i++)
{
if (i < 3)
quest = file->quest(i);
else
quest = file->quest(i - 3);
for (atUint32 i = 0; i < 6; i++) {
if (i < 3)
quest = file->quest(i);
else
quest = file->quest(i - 3);
for (int j = 0; j < 0x140; 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 < 0x140; 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));
}
}
void ALTTPFileWriter::writeRoomFlags(ALTTPRoomFlags* flags)
{
atUint8 flagsByte = 0;
flagsByte |= flags->Chest1;
flagsByte |= flags->Chest2 << 1;
flagsByte |= flags->Chest3 << 2;
flagsByte |= flags->Chest4 << 3;
flagsByte |= flags->Quadrant1 << 4;
flagsByte |= flags->Quadrant2 << 5;
flagsByte |= flags->Quadrant3 << 6;
flagsByte |= flags->Quadrant4 << 7;
writeUByte(flagsByte);
flagsByte = 0;
flagsByte |= flags->Door1;
flagsByte |= flags->Door2 << 1;
flagsByte |= flags->Door3 << 2;
flagsByte |= flags->Door4 << 3;
flagsByte |= flags->BossBattleWon << 4;
flagsByte |= flags->Key << 5;
flagsByte |= flags->KeyOrChest << 6;
flagsByte |= flags->ChestOrTile << 7;
writeUByte(flagsByte);
void ALTTPFileWriter::writeRoomFlags(ALTTPRoomFlags* flags) {
atUint8 flagsByte = 0;
flagsByte |= flags->Chest1;
flagsByte |= flags->Chest2 << 1;
flagsByte |= flags->Chest3 << 2;
flagsByte |= flags->Chest4 << 3;
flagsByte |= flags->Quadrant1 << 4;
flagsByte |= flags->Quadrant2 << 5;
flagsByte |= flags->Quadrant3 << 6;
flagsByte |= flags->Quadrant4 << 7;
writeUByte(flagsByte);
flagsByte = 0;
flagsByte |= flags->Door1;
flagsByte |= flags->Door2 << 1;
flagsByte |= flags->Door3 << 2;
flagsByte |= flags->Door4 << 3;
flagsByte |= flags->BossBattleWon << 4;
flagsByte |= flags->Key << 5;
flagsByte |= flags->KeyOrChest << 6;
flagsByte |= flags->ChestOrTile << 7;
writeUByte(flagsByte);
}
void ALTTPFileWriter::writeOverworldEvent(ALTTPOverworldEvent* event)
{
atUint8 flagsByte = 0;
flagsByte |= event->Unused1;
flagsByte |= event->HeartPiece << 1;
flagsByte |= event->Overlay << 2;
flagsByte |= event->Unused2 << 3;
flagsByte |= event->Unused3 << 4;
flagsByte |= event->Unused4 << 5;
flagsByte |= event->Set << 6;
flagsByte |= event->Unused5 << 7;
writeUByte(flagsByte);
void ALTTPFileWriter::writeOverworldEvent(ALTTPOverworldEvent* event) {
atUint8 flagsByte = 0;
flagsByte |= event->Unused1;
flagsByte |= event->HeartPiece << 1;
flagsByte |= event->Overlay << 2;
flagsByte |= event->Unused2 << 3;
flagsByte |= event->Unused3 << 4;
flagsByte |= event->Unused4 << 5;
flagsByte |= event->Set << 6;
flagsByte |= event->Unused5 << 7;
writeUByte(flagsByte);
}
void ALTTPFileWriter::writeDungeonItems(ALTTPDungeonItemFlags flags)
{
atUint8 flagsByte = 0;
flagsByte |= flags.Unused1;
flagsByte |= flags.Unused2 << 1;
flagsByte |= flags.GanonsTower << 2;
flagsByte |= flags.TurtleRock << 3;
flagsByte |= flags.TowerOfHera << 4;
flagsByte |= flags.IcePalace << 5;
flagsByte |= flags.SkullWoods << 6;
flagsByte |= flags.MiseryMire << 7;
writeUByte(flagsByte);
flagsByte = 0;
flagsByte |= flags.DarkPalace;
flagsByte |= flags.SwampPalace << 1;
flagsByte |= flags.HyruleCastle2 << 2;
flagsByte |= flags.DesertPalace << 3;
flagsByte |= flags.EasternPalace << 4;
flagsByte |= flags.HyruleCastle << 5;
flagsByte |= flags.SewerPassage << 6;
writeUByte(flagsByte);
void ALTTPFileWriter::writeDungeonItems(ALTTPDungeonItemFlags flags) {
atUint8 flagsByte = 0;
flagsByte |= flags.Unused1;
flagsByte |= flags.Unused2 << 1;
flagsByte |= flags.GanonsTower << 2;
flagsByte |= flags.TurtleRock << 3;
flagsByte |= flags.TowerOfHera << 4;
flagsByte |= flags.IcePalace << 5;
flagsByte |= flags.SkullWoods << 6;
flagsByte |= flags.MiseryMire << 7;
writeUByte(flagsByte);
flagsByte = 0;
flagsByte |= flags.DarkPalace;
flagsByte |= flags.SwampPalace << 1;
flagsByte |= flags.HyruleCastle2 << 2;
flagsByte |= flags.DesertPalace << 3;
flagsByte |= flags.EasternPalace << 4;
flagsByte |= flags.HyruleCastle << 5;
flagsByte |= flags.SewerPassage << 6;
writeUByte(flagsByte);
}
atUint16 ALTTPFileWriter::calculateChecksum(atUint32 game)
{
/*
* ALTTP's checksum is very basic
* It adds each word up and then subtracts the sum from 0x5a5a
* 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."
*
* Ignoring the algorithm for figuring out it's position in the buffer the equation is basically:
* s = s + w
* s = (0x5a5a - s);
* s == sum
* w == current word
*
* For those who don't know a word is a two byte pair, i.e 0xFF and 0xFE constitutes a word.
*/
atUint16 ALTTPFileWriter::calculateChecksum(atUint32 game) {
/*
* ALTTP's checksum is very basic
* It adds each word up and then subtracts the sum from 0x5a5a
* 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."
*
* Ignoring the algorithm for figuring out it's position in the buffer the equation is basically:
* s = s + w
* s = (0x5a5a - s);
* s == sum
* w == current 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
atUint16 sum = 0;
// First we start at 0
atUint16 sum = 0;
for (atUint32 i = 0; i < 0x4FE; i += 2)
// Add each word one by one
sum += *(atUint16*)(m_data + (i + (0x500 * game)));
for (atUint32 i = 0; i < 0x4FE; i += 2)
// Add each word one by one
sum += *(atUint16*)(m_data + (i + (0x500 * game)));
// Subtract it from 0x5a5a to get our true checksum
return (0x5a5a - sum);
// Subtract it from 0x5a5a to get our true checksum
return (0x5a5a - sum);
/*
* 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
* 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.
*/
/*
* 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
* 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.
*/
}
} // io
} // zelda
} // namespace io
} // namespace athena

File diff suppressed because it is too large Load Diff

View File

@ -3,232 +3,182 @@
#include <iostream>
#include <iomanip>
namespace athena::checksums
{
atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed, atUint64 final)
{
static const atUint64 crc64Table[256] =
{
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,
};
namespace athena::checksums {
atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed, atUint64 final) {
static const atUint64 crc64Table[256] = {
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,
};
if (!data)
return seed;
if (!data)
return seed;
atUint64 checksum = seed;
int pos = 0;
atUint64 checksum = seed;
int pos = 0;
while (length--)
checksum = crc64Table[((checksum >> 56) ^ data[pos++]) & 0xff] ^ (checksum << 8);
while (length--)
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)
{
static const atUint32 crc32Table[256] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
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
};
atUint32 crc32(const atUint8* data, atUint64 length, atUint32 seed, atUint32 final) {
static const atUint32 crc32Table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832,
0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A,
0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4,
0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76,
0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6,
0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7,
0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
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)
return seed;
if (!data)
return seed;
atUint32 checksum = seed;
int pos = 0;
atUint32 checksum = seed;
int pos = 0;
while (length--)
checksum = (checksum >> 8) ^ crc32Table[(checksum & 0xFF) ^ data[pos++]];
while (length--)
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)
{
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, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401,
0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee,
0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6,
0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d,
0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5,
0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc,
0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4,
0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd,
0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13,
0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a,
0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e,
0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1,
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 crc16CCITT(const atUint8* data, atUint64 length, atUint16 seed, atUint16 final) {
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,
0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b,
0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861,
0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96,
0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87,
0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a,
0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3,
0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 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;
int pos = 0;
atUint16 checksum = seed;
int pos = 0;
while (length--)
checksum = crc16CCITTTable[(data[pos++] ^ (checksum >> 8)) & 0xFF] ^ (checksum << 8);
while (length--)
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)
{
if (data)
return seed;
atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed, atUint64 final) {
if (data)
return seed;
static const atUint16 crc16Table[256] =
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
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
};
static const atUint16 crc16Table[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1,
0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40,
0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1,
0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1,
0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40,
0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1,
0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0,
0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740,
0xA501, 0x65C0, 0x6480, 0xA441, 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;
atUint16 checksum = seed;
atInt32 pos = 0;
atUint16 checksum = seed;
while (length--)
checksum = (crc16Table[(checksum ^ data[pos++]) & 0xFF] ^ (checksum >> 8));
while (length--)
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/LZType11.hpp"
namespace athena::io::Compression
{
namespace athena::io::Compression {
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};
strm.total_in = strm.avail_in = srcLen;
strm.total_out = strm.avail_out = dstLen;
strm.next_in = (Bytef*) src;
strm.next_out = (Bytef*) dst;
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};
strm.total_in = strm.avail_in = srcLen;
strm.total_out = strm.avail_out = dstLen;
strm.next_in = (Bytef*)src;
strm.next_out = (Bytef*)dst;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
atInt32 err = -1;
atInt32 ret = -1;
atInt32 err = -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)
{
err = inflate(&strm, Z_FINISH);
if (err == Z_OK) {
err = inflate(&strm, Z_FINISH);
if (err == Z_STREAM_END)
ret = strm.total_out;
else
{
inflateEnd(&strm);
return err;
}
if (err == Z_STREAM_END)
ret = strm.total_out;
else {
inflateEnd(&strm);
return err;
}
else
{
inflateEnd(&strm);
return err;
}
} else {
inflateEnd(&strm);
return err;
}
return ret;
inflateEnd(&strm);
return ret;
}
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};
strm.total_in = strm.avail_in = srcLen;
strm.total_out = strm.avail_out = dstLen;
strm.next_in = (Bytef*) src;
strm.next_out = (Bytef*) dst;
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};
strm.total_in = strm.avail_in = srcLen;
strm.total_out = strm.avail_out = dstLen;
strm.next_in = (Bytef*)src;
strm.next_out = (Bytef*)dst;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
atInt32 err = -1;
atInt32 ret = -1;
atInt32 err = -1;
atInt32 ret = -1;
err = deflateInit(&strm, Z_BEST_COMPRESSION);
err = deflateInit(&strm, Z_BEST_COMPRESSION);
if (err == Z_OK)
{
err = deflate(&strm, Z_FINISH);
if (err == Z_OK) {
err = deflate(&strm, Z_FINISH);
if (err == Z_STREAM_END)
ret = strm.total_out;
else
{
deflateEnd(&strm);
return err;
}
if (err == Z_STREAM_END)
ret = strm.total_out;
else {
deflateEnd(&strm);
return err;
}
else
{
deflateEnd(&strm);
return err;
}
} else {
deflateEnd(&strm);
return err;
}
return ret;
deflateEnd(&strm);
return ret;
}
atInt32 decompressLZO(const atUint8* source, const atInt32 sourceSize, atUint8* dst, atInt32& dstSize)
{
int srcSize = sourceSize;
lzo_uint size = dstSize;
int result = lzo1x_decompress_safe(source, srcSize, dst, &size, NULL);
dstSize -= (atInt32)size;
atInt32 decompressLZO(const atUint8* source, const atInt32 sourceSize, atUint8* dst, atInt32& dstSize) {
int srcSize = sourceSize;
lzo_uint size = dstSize;
int result = lzo1x_decompress_safe(source, srcSize, dst, &size, NULL);
dstSize -= (atInt32)size;
return result;
return result;
}
//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
//the second 4 bytes in the Yaz0 header).
atUint32 yaz0Decode(const atUint8* src, atUint8* dst, atUint32 uncompressedSize)
{
atUint32 srcPlace = 0, dstPlace = 0; //current read/write positions
// 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
// the second 4 bytes in the Yaz0 header).
atUint32 yaz0Decode(const atUint8* src, atUint8* dst, atUint32 uncompressedSize) {
atUint32 srcPlace = 0, dstPlace = 0; // current read/write positions
atInt32 validBitCount = 0; //number of valid bits left in "code" byte
atUint8 currCodeByte;
atInt32 validBitCount = 0; // number of valid bits left in "code" byte
atUint8 currCodeByte;
while (dstPlace < uncompressedSize)
{
//read new "code" byte if the current one is used up
if (validBitCount == 0)
{
currCodeByte = src[srcPlace];
++srcPlace;
validBitCount = 8;
}
if ((currCodeByte & 0x80) != 0)
{
//straight copy
dst[dstPlace] = src[srcPlace];
dstPlace++;
srcPlace++;
}
else
{
//RLE part
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;
while (dstPlace < uncompressedSize) {
// read new "code" byte if the current one is used up
if (validBitCount == 0) {
currCodeByte = src[srcPlace];
++srcPlace;
validBitCount = 8;
}
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
typedef struct
{
atUint32 srcPos, dstPos;
typedef struct {
atUint32 srcPos, dstPos;
} yaz0_Ret;
atUint32 simpleEnc(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)
{
yaz0_Ret r = { 0, 0 };
atInt32 pos = 0;
atUint8 dst[24]; // 8 codes * 3 bytes maximum
atUint32 dstSize = 0;
atUint32 i;
atUint32 yaz0Encode(const atUint8* src, atUint32 srcSize, atUint8* data) {
yaz0_Ret r = {0, 0};
atInt32 pos = 0;
atUint8 dst[24]; // 8 codes * 3 bytes maximum
atUint32 dstSize = 0;
atUint32 i;
atUint32 validBitCount = 0; //number of valid bits left in "code" byte
atUint8 currCodeByte = 0;
atUint32 validBitCount = 0; // number of valid bits left in "code" byte
atUint8 currCodeByte = 0;
while (r.srcPos < srcSize)
{
atUint32 numBytes;
atUint32 matchPos;
numBytes = nintendoEnc(src, srcSize, r.srcPos, &matchPos);
while (r.srcPos < srcSize) {
atUint32 numBytes;
atUint32 matchPos;
numBytes = nintendoEnc(src, srcSize, r.srcPos, &matchPos);
if (numBytes < 3)
{
//straight copy
dst[r.dstPos] = src[r.srcPos];
r.dstPos++;
r.srcPos++;
//set flag for straight copy
currCodeByte |= (0x80 >> validBitCount);
}
else
{
//RLE part
atUint32 dist = r.srcPos - matchPos - 1;
atUint8 byte1, byte2, byte3;
if (numBytes < 3) {
// straight copy
dst[r.dstPos] = src[r.srcPos];
r.dstPos++;
r.srcPos++;
// set flag for straight copy
currCodeByte |= (0x80 >> validBitCount);
} else {
// RLE part
atUint32 dist = r.srcPos - matchPos - 1;
atUint8 byte1, byte2, byte3;
if (numBytes >= 0x12) // 3 byte encoding
{
byte1 = 0 | (dist >> 8);
byte2 = dist & 0xff;
dst[r.dstPos++] = byte1;
dst[r.dstPos++] = byte2;
if (numBytes >= 0x12) // 3 byte encoding
{
byte1 = 0 | (dist >> 8);
byte2 = dist & 0xff;
dst[r.dstPos++] = byte1;
dst[r.dstPos++] = byte2;
// maximum runlength for 3 byte encoding
if (numBytes > 0xff + 0x12)
numBytes = 0xff + 0x12;
// maximum runlength for 3 byte encoding
if (numBytes > 0xff + 0x12)
numBytes = 0xff + 0x12;
byte3 = numBytes - 0x12;
dst[r.dstPos++] = byte3;
}
else // 2 byte encoding
{
byte1 = ((numBytes - 2) << 4) | (dist >> 8);
byte2 = dist & 0xff;
dst[r.dstPos++] = byte1;
dst[r.dstPos++] = byte2;
}
byte3 = numBytes - 0x12;
dst[r.dstPos++] = byte3;
} else // 2 byte encoding
{
byte1 = ((numBytes - 2) << 4) | (dist >> 8);
byte2 = dist & 0xff;
dst[r.dstPos++] = byte1;
dst[r.dstPos++] = byte2;
}
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;
}
r.srcPos += numBytes;
}
if (validBitCount > 0)
{
data[pos] = currCodeByte;
pos++;
validBitCount++;
for (i = 0; i </*=*/r.dstPos; pos++, i++)
data[pos] = dst[i];
// write eight codes
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;
validBitCount = 0;
r.dstPos = 0;
dstSize += r.dstPos + 1;
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
atUint32 nintendoEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos)
{
atUint32 numBytes = 1;
static atUint32 numBytes1;
static atUint32 matchPos;
static atInt32 prevFlag = 0;
atUint32 nintendoEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos) {
atUint32 numBytes = 1;
static atUint32 numBytes1;
static atUint32 matchPos;
static atInt32 prevFlag = 0;
// 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.
if (prevFlag == 1)
{
*pMatchPos = matchPos;
prevFlag = 0;
return numBytes1;
}
prevFlag = 0;
numBytes = simpleEnc(src, size, pos, &matchPos);
// 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.
if (prevFlag == 1) {
*pMatchPos = matchPos;
prevFlag = 0;
return numBytes1;
}
// if this position is RLE encoded, then compare to copying 1 byte and next position(pos+1) encoding
if (numBytes >= 3)
{
numBytes1 = simpleEnc(src, size, pos + 1, &matchPos);
prevFlag = 0;
numBytes = simpleEnc(src, size, pos, &matchPos);
*pMatchPos = matchPos;
// if the next position encoding is +2 longer than current position, choose it.
// this does not guarantee the best optimization, but fairly good optimization with speed.
if (numBytes1 >= numBytes + 2)
{
numBytes = 1;
prevFlag = 1;
}
// if this position is RLE encoded, then compare to copying 1 byte and next position(pos+1) encoding
if (numBytes >= 3) {
numBytes1 = simpleEnc(src, size, pos + 1, &matchPos);
// if the next position encoding is +2 longer than current position, choose it.
// 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
atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos)
{
int startPos = pos - 0x1000, j, i;
atUint32 numBytes = 1;
atUint32 matchPos = 0;
atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos) {
int startPos = pos - 0x1000, j, i;
atUint32 numBytes = 1;
atUint32 matchPos = 0;
if (startPos < 0)
startPos = 0;
if (startPos < 0)
startPos = 0;
for (i = startPos; i < pos; i++)
{
for (j = 0; j < size - pos; j++)
{
if (src[i + j] != src[j + pos])
break;
}
if ((atUint32)j > numBytes)
{
numBytes = j;
matchPos = i;
}
for (i = startPos; i < pos; i++) {
for (j = 0; j < size - pos; j++) {
if (src[i + j] != src[j + pos])
break;
}
*pMatchPos = matchPos;
if ((atUint32)j > numBytes) {
numBytes = j;
matchPos = i;
}
}
if (numBytes == 2)
numBytes = 1;
*pMatchPos = matchPos;
return numBytes;
if (numBytes == 2)
numBytes = 1;
return numBytes;
}
atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst)
{
if (*(atUint8*)src == 0x11)
return LZType11().decompress(src, dst, srcLen);
atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst) {
if (*(atUint8*)src == 0x11)
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)
{
if (extended)
return LZType11().compress(src, dst, srcLen);
atUint32 compressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst, bool extended) {
if (extended)
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)
#endif
namespace athena
{
Dir::Dir(std::string_view path)
: m_path(path)
{
}
namespace athena {
Dir::Dir(std::string_view path) : m_path(path) {}
std::string Dir::absolutePath() const
{
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;
}
std::string Dir::absolutePath() const { 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::rm(std::string_view path)
{
return !(remove((m_path + "/" + path.data()).c_str()) < 0);
bool Dir::cd(std::string_view path) {
Dir tmp(path);
if (tmp.isDir()) {
m_path = path;
return true;
}
return false;
}
bool Dir::touch()
{
srand(time(NULL));
atUint64 tmp = utility::rand64();
std::string tmpFile = utility::sprintf("%" PRIX64 ".tmp", tmp);
bool ret = FileInfo(m_path + "/" + tmpFile).touch();
if (ret)
return rm(tmpFile);
return false;
bool Dir::rm(std::string_view path) { return !(remove((m_path + "/" + path.data()).c_str()) < 0); }
bool Dir::touch() {
srand(time(NULL));
atUint64 tmp = utility::rand64();
std::string tmpFile = utility::sprintf("%" PRIX64 ".tmp", tmp);
bool ret = FileInfo(m_path + "/" + tmpFile).touch();
if (ret)
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
return !(::_mkdir(dir.data()) < 0);
return !(::_mkdir(dir.data()) < 0);
#else
return !(::mkdir(dir.data(), mode) < 0);
return !(::mkdir(dir.data(), mode) < 0);
#endif
}
bool Dir::mkpath(std::string_view path, mode_t mode)
{
std::vector<std::string> dirs = utility::split(path, '/');
if (dirs.empty())
dirs = utility::split(path, '\\');
if (dirs.empty())
return false;
bool Dir::mkpath(std::string_view path, mode_t mode) {
std::vector<std::string> dirs = utility::split(path, '/');
if (dirs.empty())
dirs = utility::split(path, '\\');
if (dirs.empty())
return false;
bool ret = false;
std::string newPath;
for (const std::string& dir : dirs)
{
if (dir.size() == 2 && dir[1] == ':')
{
newPath += dir + "//";
continue;
}
newPath += "/" + dir;
ret = mkdir(newPath, mode);
bool ret = false;
std::string newPath;
for (const std::string& dir : dirs) {
if (dir.size() == 2 && dir[1] == ':') {
newPath += dir + "//";
continue;
}
newPath += "/" + dir;
ret = mkdir(newPath, mode);
}
// we only care if the last directory was created
return ret;
}
// we only care if the last directory was created
return ret;
}
} // namespace athena

View File

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

View File

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

View File

@ -1,233 +1,196 @@
#include "athena/FileReader.hpp"
#include "win32_largefilewrapper.h"
namespace athena::io
{
namespace athena::io {
FileReader::FileReader(std::string_view filename, atInt32 cacheSize, bool globalErr)
: m_fileHandle(nullptr),
m_cacheData(nullptr),
m_offset(0),
m_globalErr(globalErr)
{
m_filename = utility::utf8ToWide(filename);
open();
setCacheSize(cacheSize);
: m_fileHandle(nullptr), m_cacheData(nullptr), m_offset(0), m_globalErr(globalErr) {
m_filename = utility::utf8ToWide(filename);
open();
setCacheSize(cacheSize);
}
FileReader::FileReader(std::wstring_view filename, atInt32 cacheSize, bool globalErr)
: m_fileHandle(nullptr),
m_cacheData(nullptr),
m_offset(0),
m_globalErr(globalErr)
{
m_filename = filename;
open();
setCacheSize(cacheSize);
: m_fileHandle(nullptr), m_cacheData(nullptr), m_offset(0), m_globalErr(globalErr) {
m_filename = filename;
open();
setCacheSize(cacheSize);
}
FileReader::~FileReader()
{
if (isOpen())
close();
FileReader::~FileReader() {
if (isOpen())
close();
}
void FileReader::open()
{
int attempt = 0;
do
{
void FileReader::open() {
int attempt = 0;
do {
#if WINDOWS_STORE
m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ,
OPEN_EXISTING, nullptr);
m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
#else
m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, nullptr);
#endif
} while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100);
} while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100);
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);
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::seek(atInt64 pos, SeekOrigin origin)
{
if (!isOpen())
return;
void FileReader::close() {
if (!m_fileHandle) {
if (m_globalErr)
atError("Cannot close an unopened stream");
setError();
return;
}
// check block position
if (m_blockSize > 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;
}
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();
}
}
CloseHandle(m_fileHandle);
m_fileHandle = 0;
return;
}
atUint64 FileReader::position() const
{
if (!isOpen())
{
if (m_globalErr)
atError("File not open");
return 0;
void FileReader::seek(atInt64 pos, SeekOrigin origin) {
if (!isOpen())
return;
// check block position
if (m_blockSize > 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)
return m_offset;
else
{
LARGE_INTEGER li = {};
LARGE_INTEGER res;
SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT);
return res.QuadPart;
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::length() const
{
if (!isOpen())
{
if (m_globalErr)
atError("File not open");
return 0;
}
atUint64 FileReader::position() const {
if (!isOpen()) {
if (m_globalErr)
atError("File not open");
return 0;
}
if (m_blockSize > 0)
return m_offset;
else {
LARGE_INTEGER li = {};
LARGE_INTEGER res;
GetFileSizeEx(m_fileHandle, &res);
SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT);
return res.QuadPart;
}
}
atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len)
{
if (!isOpen())
{
if (m_globalErr)
atError("File not open for reading");
setError();
return 0;
}
atUint64 FileReader::length() const {
if (!isOpen()) {
if (m_globalErr)
atError("File not open");
return 0;
}
if (m_blockSize <= 0)
{
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;
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;
}
LARGE_INTEGER res;
GetFileSizeEx(m_fileHandle, &res);
return res.QuadPart;
}
void FileReader::setCacheSize(const atInt32 blockSize)
{
m_blockSize = blockSize;
atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) {
if (!isOpen()) {
if (m_globalErr)
atError("File not open for reading");
setError();
return 0;
}
if (m_blockSize > length())
m_blockSize = (atInt32)length();
if (m_blockSize <= 0) {
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;
if (m_blockSize > 0)
m_cacheData.reset(new atUint8[m_blockSize]);
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;
}
}
} // 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"
namespace athena::io
{
void TransactionalFileWriter::seek(atInt64 pos, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin::Begin:
m_position = pos;
break;
case SeekOrigin::Current:
m_position += pos;
break;
case SeekOrigin::End:
break;
}
namespace athena::io {
void TransactionalFileWriter::seek(atInt64 pos, SeekOrigin origin) {
switch (origin) {
case SeekOrigin::Begin:
m_position = pos;
break;
case SeekOrigin::Current:
m_position += pos;
break;
case SeekOrigin::End:
break;
}
}
void TransactionalFileWriter::writeUBytes(const atUint8* data, atUint64 len)
{
atUint64 neededSz = m_position + len;
if (neededSz > m_deferredBuffer.size())
{
m_deferredBuffer.reserve(neededSz * 2);
m_deferredBuffer.resize(neededSz);
}
void TransactionalFileWriter::writeUBytes(const atUint8* data, atUint64 len) {
atUint64 neededSz = m_position + len;
if (neededSz > m_deferredBuffer.size()) {
m_deferredBuffer.reserve(neededSz * 2);
m_deferredBuffer.resize(neededSz);
}
memmove(m_deferredBuffer.data() + m_position, data, len);
m_position += len;
}
memmove(m_deferredBuffer.data() + m_position, data, len);
m_position += len;
}
} // namespace athena::io

View File

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

View File

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

View File

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

View File

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

View File

@ -1,49 +1,39 @@
#include "athena/MCFileWriter.hpp"
namespace athena::io
{
namespace athena::io {
MCFileWriter::MCFileWriter(atUint8* data, atUint64 length)
: MemoryCopyWriter(data, length)
{
}
MCFileWriter::MCFileWriter(atUint8* data, atUint64 length) : MemoryCopyWriter(data, length) {}
MCFileWriter::MCFileWriter(const std::string& filename)
: MemoryCopyWriter(filename)
{
}
MCFileWriter::MCFileWriter(const std::string& filename) : MemoryCopyWriter(filename) {}
// 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
// need to figure out what it's doing and whether it's relevant to the checksum.
atUint16 MCFileWriter::calculateSlotChecksum(atUint32 game)
{
atUint16 first = calculateChecksum((m_data + 0x34 + (0x10 * game)), 4);
atUint16 second = calculateChecksum((m_data + 0x80 + (0x500 * game)), 0x500);
atUint16 MCFileWriter::calculateSlotChecksum(atUint32 game) {
atUint16 first = calculateChecksum((m_data + 0x34 + (0x10 * game)), 4);
atUint16 second = calculateChecksum((m_data + 0x80 + (0x500 * game)), 0x500);
first = (first + second) & 0xFFFF;
atUint16 result = first << 16;
second = ~first & 0xFFFF;
second += 1;
result += second;
first = (first + second) & 0xFFFF;
atUint16 result = first << 16;
second = ~first & 0xFFFF;
second += 1;
result += second;
return result;
return result;
}
atUint16 MCFileWriter::calculateChecksum(atUint8* data, atUint32 length)
{
atUint16 sum = 0;
int i = length;
atUint16 MCFileWriter::calculateChecksum(atUint8* data, atUint32 length) {
atUint16 sum = 0;
int i = length;
for (atUint32 j = 0; j < length; j += 2)
{
sum += *(atUint16*)(data + j) ^ i;
i -= 2;
}
for (atUint32 j = 0; j < length; j += 2) {
sum += *(atUint16*)(data + j) ^ i;
i -= 2;
}
sum &= 0xFFFF;
sum &= 0xFFFF;
return sum;
return sum;
}
} // zelda
} // namespace athena::io

View File

@ -1,11 +1,8 @@
#include "athena/MCSlot.hpp"
namespace athena
{
namespace athena {
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 max
namespace athena::io
{
namespace athena::io {
MemoryReader::MemoryReader(const void* data, atUint64 length, bool takeOwnership, bool globalErr)
: m_data(data),
m_length(length),
m_position(0),
m_owns(takeOwnership),
m_globalErr(globalErr)
{
if (!data)
{
if (m_globalErr)
atError("data cannot be NULL");
setError();
return;
}
: m_data(data), m_length(length), m_position(0), m_owns(takeOwnership), m_globalErr(globalErr) {
if (!data) {
if (m_globalErr)
atError("data cannot be NULL");
setError();
return;
}
}
MemoryReader::~MemoryReader()
{
if (m_owns)
delete[] reinterpret_cast<const atUint8*>(m_data);
MemoryReader::~MemoryReader() {
if (m_owns)
delete[] reinterpret_cast<const atUint8*>(m_data);
}
MemoryCopyReader::MemoryCopyReader(const void* data, atUint64 length)
: MemoryReader(data, length, false)
{
if (!data)
{
if (m_globalErr)
atError("data cannot be NULL");
setError();
return;
MemoryCopyReader::MemoryCopyReader(const void* data, atUint64 length) : MemoryReader(data, length, false) {
if (!data) {
if (m_globalErr)
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_data = m_dataCopy.get();
memmove(m_dataCopy.get(), data, m_length);
}
m_position = position;
break;
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_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;
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;
}
length = std::min(length, m_length - m_position);
memmove(buf, reinterpret_cast<const atUint8*>(m_data) + m_position, length);
m_position += length;
return length;
}
m_position += position;
break;
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;
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;
}
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;
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);
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>
#endif // HW_RVL
namespace athena::io
{
namespace athena::io {
MemoryWriter::MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership)
: m_data((atUint8*)data),
m_length(length),
m_position(0),
m_bufferOwned(takeOwnership)
{
if (!data)
{
atError("data cannot be NULL");
setError();
return;
}
: m_data((atUint8*)data), m_length(length), m_position(0), m_bufferOwned(takeOwnership) {
if (!data) {
atError("data cannot be NULL");
setError();
return;
}
}
MemoryWriter::~MemoryWriter()
{
if (m_bufferOwned)
delete m_data;
m_data = nullptr;
m_length = 0;
MemoryWriter::~MemoryWriter() {
if (m_bufferOwned)
delete m_data;
m_data = nullptr;
m_length = 0;
}
MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length)
{
m_data = data;
m_length = length;
m_position = 0;
m_bufferOwned = false;
MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) {
m_data = data;
m_length = length;
m_position = 0;
m_bufferOwned = false;
if (length == 0)
{
atError("length cannot be 0");
setError();
return;
}
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
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();
if (length == 0) {
atError("length cannot be 0");
setError();
return;
}
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
if (data)
memmove(m_data, data, length);
m_length = length;
m_position = 0;
m_bufferOwned = false;
}
atUint8* MemoryWriter::data() const
{
atUint8* ret = new atUint8[m_length];
memset(ret, 0, m_length);
memmove(ret, m_data, m_length);
return ret;
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::save(std::string_view filename)
{
if (filename.empty() && m_filepath.empty())
{
atError("No file specified, cannot save.");
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 (!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;
if ((atUint64)position > m_length) {
atError("data exceeds available buffer space");
setError();
return;
}
atUint64 done = 0;
atUint64 blocksize = BLOCKSZ;
m_position = position;
break;
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;
case SeekOrigin::Current:
if ((((atInt64)m_position + position) < 0)) {
atError("Position outside stream bounds");
setError();
return;
}
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)
{
if (!data)
{
atError("data cannnot be NULL");
setError();
return;
void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin) {
switch (origin) {
case SeekOrigin::Begin:
if (position < 0) {
atError("Position outside stream bounds");
setError();
return;
}
if (m_position + length > m_length)
{
atError("data length exceeds available buffer space");
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;
}
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)
{
if (!data)
{
atError("data cannnot be NULL");
setError();
return;
}
void MemoryWriter::setData(atUint8* data, atUint64 length, bool takeOwnership) {
if (m_bufferOwned)
delete m_data;
if (m_position + length > m_length)
resize(m_position + length);
memmove(reinterpret_cast<atInt8*>(m_data + m_position), data, length);
m_position += length;
m_data = (atUint8*)data;
m_length = length;
m_position = 0;
m_bufferOwned = takeOwnership;
}
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;
void MemoryCopyWriter::setData(const atUint8* data, atUint64 length) {
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
memmove(m_data, data, length);
m_length = length;
m_position = 0;
m_bufferOwned = false;
}
} // 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/IOException.hpp"
namespace athena::io
{
namespace athena::io {
PHYSFSFileReader::PHYSFSFileReader(const std::string& path)
: m_path(path),
m_endian(Endian::LittleEndian)
{
if (!PHYSFS_exists(m_path.c_str()))
THROW_FILE_NOT_FOUND_EXCEPTION(path);
PHYSFSFileReader::PHYSFSFileReader(const std::string& path) : m_path(path), m_endian(Endian::LittleEndian) {
if (!PHYSFS_exists(m_path.c_str()))
THROW_FILE_NOT_FOUND_EXCEPTION(path);
m_handle = PHYSFS_openRead(path.c_str());
m_length = PHYSFS_fileLength(m_handle);
m_handle = PHYSFS_openRead(path.c_str());
m_length = PHYSFS_fileLength(m_handle);
}
atUint8* PHYSFSFileReader::data()
{
return readUBytes(length());
atUint8* PHYSFSFileReader::data() { 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
{
return m_length;
}
atUint8 PHYSFSFileReader::readUByte() {
atUint8 val;
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;
}
}
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;
if (!PHYSFS_read(m_handle, &val, 1, 1))
THROW_IO_EXCEPTION("Position outside stream bounds");
return val;
}
atInt8* PHYSFSFileReader::readBytes(atUint64 length)
{
return (atInt8*)readUBytes(length);
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");
}
atUint16 PHYSFSFileReader::readUint16()
{
atUint16 val;
atInt8* PHYSFSFileReader::readBytes(atUint64 length) { return (atInt8*)readUBytes(length); }
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");
atUint16 PHYSFSFileReader::readUint16() {
atUint16 val;
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()
{
return readUint16();
atInt16 PHYSFSFileReader::readInt16() { 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()
{
atUint32 val;
atInt32 PHYSFSFileReader::readInt32() { return readUint32(); }
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");
atUint64 PHYSFSFileReader::readUint64() {
atUint64 val;
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()
{
return readUint32();
}
atInt64 PHYSFSFileReader::readInt64() { return readUint64(); }
atUint64 PHYSFSFileReader::readUint64()
{
atUint64 val;
double PHYSFSFileReader::readDouble() { return static_cast<double>(readUint64()); }
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");
float PHYSFSFileReader::readFloat() { return static_cast<float>(readUint32()); }
return val;
}
bool PHYSFSFileReader::readBool() { return (readByte() != 0); }
atInt64 PHYSFSFileReader::readInt64()
{
return readUint64();
}
bool PHYSFSFileReader::atEnd() const { return PHYSFS_eof(m_handle); }
double PHYSFSFileReader::readDouble()
{
return static_cast<double>(readUint64());
}
void PHYSFSFileReader::setEndian(Endian endian) { m_endian = endian; }
float PHYSFSFileReader::readFloat()
{
return static_cast<float>(readUint32());
}
Endian PHYSFSFileReader::endian() const { return m_endian; }
bool PHYSFSFileReader::readBool()
{
return (readByte() != 0);
}
bool PHYSFSFileReader::isBigEndian() const { return m_endian == Endian::BigEndian; }
bool PHYSFSFileReader::atEnd() const
{
return PHYSFS_eof(m_handle);
}
bool PHYSFSFileReader::isLittleEndian() const { return m_endian == Endian::LittleEndian; }
void PHYSFSFileReader::setEndian(Endian endian)
{
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;
}
}
} // namespace athena::io
#endif

View File

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

View File

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

View File

@ -2,62 +2,54 @@
#include "athena/SkywardSwordFile.hpp"
#include "athena/SkywardSwordQuest.hpp"
namespace athena::io
{
namespace athena::io {
SkywardSwordFileWriter::SkywardSwordFileWriter(atUint8* data, atUint64 len)
: MemoryCopyWriter(data, len)
{
setEndian(Endian::Big);
SkywardSwordFileWriter::SkywardSwordFileWriter(atUint8* data, atUint64 len) : MemoryCopyWriter(data, len) {
setEndian(Endian::Big);
}
SkywardSwordFileWriter::SkywardSwordFileWriter(const std::string& filename)
: MemoryCopyWriter(filename)
{
setEndian(Endian::Big);
SkywardSwordFileWriter::SkywardSwordFileWriter(const std::string& filename) : MemoryCopyWriter(filename) {
setEndian(Endian::Big);
}
void SkywardSwordFileWriter::write(SkywardSwordFile* file)
{
if (!file)
{
atError("file cannot be NULL");
return;
void SkywardSwordFileWriter::write(SkywardSwordFile* file) {
if (!file) {
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 :
(file->region() == Region::NTSCJ ? SkywardSwordFile::JAMagic : SkywardSwordFile::EUMagic));
// 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++;
}
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;
}
// 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();
// 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