* Major rewrite

This commit is contained in:
2014-04-20 02:14:15 -07:00
parent 1a389de296
commit ec4167abca
125 changed files with 5582 additions and 6434 deletions

View File

@@ -1,24 +1,24 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "ALTTPFile.hpp"
#include "ALTTPQuest.hpp"
#include "Athena/ALTTPFile.hpp"
#include "Athena/ALTTPQuest.hpp"
#include "InvalidOperationException.hpp"
#include "Athena/InvalidOperationException.hpp"
namespace zelda
namespace Athena
{
ALTTPFile::ALTTPFile()
{}
@@ -32,7 +32,7 @@ ALTTPFile::ALTTPFile(std::vector<ALTTPQuest*> quests, std::vector<ALTTPQuest*> b
void ALTTPFile::setQuest(Uint32 id, ALTTPQuest* val)
{
if (id > m_quests.size())
throw error::InvalidOperationException("ALTTPFile::setQuest -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
m_quests[id] = val;
}
@@ -44,7 +44,7 @@ std::vector<ALTTPQuest*> ALTTPFile::questList() const
ALTTPQuest* ALTTPFile::quest(Uint32 id) const
{
if (id > m_quests.size())
throw error::InvalidOperationException("ALTTPFile::setQuest -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
return m_quests[id];
}

View File

@@ -1,24 +1,24 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "ALTTPFileReader.hpp"
#include "ALTTPFile.hpp"
#include "ALTTPQuest.hpp"
#include "Athena/ALTTPFileReader.hpp"
#include "Athena/ALTTPFile.hpp"
#include "Athena/ALTTPQuest.hpp"
#include <iostream>
namespace zelda
namespace Athena
{
namespace io
{
@@ -64,12 +64,12 @@ ALTTPFile* ALTTPFileReader::readFile()
quest->setOverworldEvents(owEvents);
quest->setInventory((ALTTPInventory*)base::readBytes(sizeof(ALTTPInventory)));
quest->setRupeeMax(base::readUInt16());
quest->setRupeeCurrent(base::readUInt16());
quest->setRupeeMax(base::readUint16());
quest->setRupeeCurrent(base::readUint16());
quest->setCompasses(readDungeonFlags());
quest->setBigKeys(readDungeonFlags());
quest->setDungeonMaps(readDungeonFlags());
quest->setWishingPond(base::readUInt16());
quest->setWishingPond(base::readUint16());
quest->setHealthMax(base::readByte());
quest->setHealth(base::readByte());
quest->setMagicPower(base::readByte());
@@ -142,26 +142,26 @@ ALTTPFile* ALTTPFileReader::readFile()
j = 6;
while((j--) > 0)
{
playerName.push_back(base::readUInt16());
playerName.push_back(base::readUint16());
}
quest->setPlayerName(playerName);
quest->setValid((base::readUInt16() == 0x55AA));
quest->setValid((base::readUint16() == 0x55AA));
j = 0x0D;
while((j--) > 0)
{
dungeonDeaths.push_back(base::readUInt16());
dungeonDeaths.push_back(base::readUint16());
}
quest->setDungeonDeathTotals(dungeonDeaths);
quest->setUnknown2(base::readUInt16());
quest->setDeathSaveCount(base::readUInt16());
quest->setUnknown2(base::readUint16());
quest->setDeathSaveCount(base::readUint16());
quest->setPostGameDeathCounter(base::readInt16());
base::seek(0xF7);
quest->setChecksum(base::readUInt16());
quest->setChecksum(base::readUint16());
if (i < 3)
quests.push_back(quest);

View File

@@ -1,24 +1,24 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "ALTTPFileWriter.hpp"
#include "ALTTPFile.hpp"
#include "ALTTPQuest.hpp"
#include "Athena/ALTTPFileWriter.hpp"
#include "Athena/ALTTPFile.hpp"
#include "Athena/ALTTPQuest.hpp"
#include <iostream>
namespace zelda
namespace Athena
{
namespace io
@@ -55,12 +55,12 @@ void ALTTPFileWriter::writeFile(ALTTPFile* file)
}
base::writeBytes((Int8*)quest->inventory(), sizeof(ALTTPInventory));
base::writeUInt16(quest->rupeeMax());
base::writeUInt16(quest->rupeeCurrent());
base::writeUint16(quest->rupeeMax());
base::writeUint16(quest->rupeeCurrent());
writeDungeonItems(quest->compasses());
writeDungeonItems(quest->bigKeys());
writeDungeonItems(quest->dungeonMaps());
base::writeUInt16(quest->wishingPond());
base::writeUint16(quest->wishingPond());
base::writeByte(quest->healthMax());
base::writeByte(quest->health());
base::writeByte(quest->magicPower());
@@ -116,20 +116,20 @@ void ALTTPFileWriter::writeFile(ALTTPFile* file)
base::writeByte(quest->unknown1(j));
for (int j = 0; j < 6; j++)
base::writeUInt16(quest->playerName()[j]);
base::writeUint16(quest->playerName()[j]);
base::writeUInt16((quest->valid() == true ? 0x55AA : 0));
base::writeUint16((quest->valid() == true ? 0x55AA : 0));
for (int j = 0; j < 0x0D; j++)
base::writeUInt16(quest->dungeonDeathTotal(j));
base::writeUint16(quest->dungeonDeathTotal(j));
base::writeUInt16(quest->unknown2());
base::writeUInt16(quest->deathSaveCount());
base::writeUInt16(quest->postGameDeathCounter());
base::writeUint16(quest->unknown2());
base::writeUint16(quest->deathSaveCount());
base::writeUint16(quest->postGameDeathCounter());
base::seek(0xF7);
base::writeUInt16(calculateChecksum(i));
base::writeUint16(calculateChecksum(i));
}
}

View File

@@ -1,23 +1,23 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "ALTTPQuest.hpp"
#include "InvalidOperationException.hpp"
#include "Athena/ALTTPQuest.hpp"
#include "Athena/InvalidOperationException.hpp"
#include <iostream>
namespace zelda
namespace Athena
{
ALTTPQuest::ALTTPQuest()
@@ -71,7 +71,7 @@ std::vector<ALTTPOverworldEvent*> ALTTPQuest::overworldEvents() const
ALTTPOverworldEvent* ALTTPQuest::overworldEvent(Uint32 id) const
{
if (id > m_overworldEvents.size() - 1)
throw error::InvalidOperationException("ALTTPQuest::overworldEvents -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
return m_overworldEvents[id];
}
@@ -301,7 +301,7 @@ void ALTTPQuest::setDungeonKeys(std::vector<Uint8> val)
void ALTTPQuest::setDungeonKeys(Uint32 id, Uint8 val)
{
if (id > m_dungeonKeys.size() - 1)
throw error::InvalidOperationException("ALTTPQuest::setDungeonKeys -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
m_dungeonKeys[id] = val;
}
@@ -309,7 +309,7 @@ void ALTTPQuest::setDungeonKeys(Uint32 id, Uint8 val)
Uint8 ALTTPQuest::dungeonKeys(Uint32 id) const
{
if (id > m_dungeonKeys.size() - 1)
throw error::InvalidOperationException("ALTTPQuest::dungeonKeys -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
return m_dungeonKeys[id];
}
@@ -398,7 +398,7 @@ void ALTTPQuest::setOldManFlags(std::vector<Uint8> flags)
void ALTTPQuest::setOldManFlag(Uint32 id, Uint8 val)
{
if (id > m_oldManFlags.size() - 1)
throw error::InvalidOperationException("ALTTPQuest::setOldManFlag -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
m_oldManFlags[id] = val;
}
@@ -406,7 +406,7 @@ void ALTTPQuest::setOldManFlag(Uint32 id, Uint8 val)
Uint8 ALTTPQuest::oldManFlag(Uint32 id)
{
if (id > m_oldManFlags.size() - 1)
throw error::InvalidOperationException("ALTTPQuest::oldManFlag -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
return m_oldManFlags[id];
}
@@ -434,7 +434,7 @@ void ALTTPQuest::setUnknown1(std::vector<Uint8> flags)
void ALTTPQuest::setUnknown1(Uint32 id, Uint8 val)
{
if (id > m_unknown1.size())
throw error::InvalidOperationException("ALTTPQuest::setUnknown1) -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
m_unknown1[id] = val;
}
@@ -442,7 +442,7 @@ void ALTTPQuest::setUnknown1(Uint32 id, Uint8 val)
Uint8 ALTTPQuest::unknown1(Uint32 id)
{
if (id > m_unknown1.size())
throw error::InvalidOperationException("ALTTPQuest::unknown1 -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
return m_unknown1[id];
}
@@ -460,7 +460,7 @@ void ALTTPQuest::setPlayerName(std::vector<Uint16> playerName)
void ALTTPQuest::setPlayerName(const std::string& playerName)
{
if (playerName == std::string() || playerName.size() > 6)
throw error::InvalidOperationException("ALTTPQuest::setPlayerName -> playerName invalid");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
m_playerName.clear();
@@ -623,7 +623,7 @@ void ALTTPQuest::setDungeonDeathTotals(std::vector<Uint16> val)
void ALTTPQuest::setDungeonDeathTotal(Uint32 id, Uint16 val)
{
if (id > m_dungeonDeathTotals.size())
throw error::InvalidOperationException("ALTTPQuest::setDungeonDeathTotal -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
m_dungeonDeathTotals[id] = val;
}
@@ -631,7 +631,7 @@ void ALTTPQuest::setDungeonDeathTotal(Uint32 id, Uint16 val)
Uint16 ALTTPQuest::dungeonDeathTotal(Uint32 id) const
{
if (id > m_dungeonDeathTotals.size())
throw error::InvalidOperationException("ALTTPQuest::setDungeonDeathTotal -> index out of range");
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
return m_dungeonDeathTotals[id];
}

506
src/Athena/BinaryReader.cpp Normal file
View File

@@ -0,0 +1,506 @@
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/BinaryReader.hpp"
#include "Athena/IOException.hpp"
#include "Athena/FileNotFoundException.hpp"
#include "Athena/InvalidDataException.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "utf8.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <cstring>
#ifdef HW_RVL
#include <malloc.h>
#endif // HW_RVL
namespace Athena
{
namespace io
{
BinaryReader::BinaryReader(const Uint8* data, Uint64 length)
: m_length(length),
m_position(0),
m_bitPosition(0),
m_endian(Endian::LittleEndian),
m_progressCallback(nullptr)
{
if (!data)
THROW_INVALID_DATA_EXCEPTION("data cannot be NULL");
if (length == 0)
THROW_INVALID_OPERATION_EXCEPTION("length cannot be 0");
m_data = new Uint8[m_length];
memcpy(m_data, data, m_length);
}
BinaryReader::BinaryReader(const std::string& filename, std::function<void(int)> progFun)
: m_data(NULL),
m_length(0),
m_filepath(filename),
m_position(0),
m_bitPosition(0),
m_endian(Endian::LittleEndian),
m_progressCallback(progFun)
{
loadData();
}
BinaryReader::~BinaryReader()
{
delete[] m_data;
m_data = NULL;
}
void BinaryReader::setEndian(Endian endian)
{
m_endian = endian;
}
Endian BinaryReader::endian() const
{
return m_endian;
}
bool BinaryReader::isBigEndian() const
{
return (m_endian == Endian::BigEndian);
}
bool BinaryReader::isLittleEndian() const
{
return (m_endian == Endian::LittleEndian);
}
bool BinaryReader::isOpen() const
{
return m_data != nullptr;
}
void BinaryReader::seek(Int64 position, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin::Begin:
if ((position < 0 || (Int64)position > (Int64)m_length))
THROW_IO_EXCEPTION("Position outside stream bounds");
m_position = position;
break;
case SeekOrigin::Current:
if ((((Int64)m_position + position) < 0 || (m_position + position) > m_length))
THROW_IO_EXCEPTION("Position outside stream bounds");
m_position += position;
break;
case SeekOrigin::End:
if ((((Int64)m_length - position < 0) || (m_length - position) > m_length))
THROW_IO_EXCEPTION("Position outside stream bounds");
m_position = m_length - position;
break;
}
}
bool BinaryReader::atEnd() const
{
return m_position >= m_length;
}
Uint64 BinaryReader::position() const
{
return m_position;
}
Uint64 BinaryReader::length() const
{
return m_length;
}
void BinaryReader::setData(const Uint8* data, Uint64 length)
{
if (m_data)
#ifdef HW_RVL
free(m_data);
#else
delete[] m_data;
#endif
m_data = (Uint8*)data;
m_length = length;
m_position = 0;
m_bitPosition = 0;
}
Uint8* BinaryReader::data() const
{
Uint8* ret = new Uint8[m_length];
memset(ret, 0, m_length);
memcpy(ret, m_data, m_length);
return ret;
}
void BinaryReader::seekBit(int bit)
{
if (!m_data)
loadData();
if (bit < 0 || bit > 7)
THROW_INVALID_OPERATION_EXCEPTION("bit out of range");
m_bitPosition = bit;
}
bool BinaryReader::readBit()
{
if (!m_data)
loadData();
if (m_position > m_length)
THROW_IO_EXCEPTION("Position outside stream bounds");
bool ret = (*(Uint8*)(m_data + m_position) & (1 << m_bitPosition));
m_bitPosition++;
if (m_bitPosition > 7)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
return ret;
}
Int8 BinaryReader::readByte()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + 1 > m_length)
THROW_IO_EXCEPTION("Stream::readByte -> Position passed stream bounds");
return *(Int8*)(m_data + m_position++);
}
Uint8 BinaryReader::readUByte()
{
if (!m_data)
loadData();
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + 1 > m_length)
THROW_IO_EXCEPTION("Position passed stream bounds");
return *(Uint8*)(m_data + m_position++);
}
Int8* BinaryReader::readBytes(Int64 length)
{
return (Int8*)readUBytes(length);
}
Uint8* BinaryReader::readUBytes(Int64 length)
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + length > m_length)
THROW_IO_EXCEPTION("Position passed stream bounds");
Uint8* ret;
#ifdef HW_RVL
ret = (Uint8*)memalign(32, length);
#else
ret = new Uint8[length];
#endif
memcpy(ret, (const Uint8*)(m_data + m_position), length);
m_position += length;
return ret;
}
Int16 BinaryReader::readInt16()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int16) > m_length)
THROW_IO_EXCEPTION("Position outside stream bounds");
Int16 ret = *(Int16*)(m_data + m_position);
m_position += sizeof(Int16);
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
ret = utility::swap16(ret);
return ret;
}
Uint16 BinaryReader::readUint16()
{
return readInt16();
}
Int32 BinaryReader::readInt32()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int32) > m_length)
THROW_IO_EXCEPTION("Position outside stream bounds");
Int32 ret = *(Int32*)(m_data + m_position);
m_position += 4;
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
ret = utility::swap32(ret);
return ret;
}
Uint32 BinaryReader::readUint32()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint32) > m_length)
THROW_IO_EXCEPTION("Position outside stream bounds");
Uint32 ret = *(Uint32*)(m_data + m_position);
m_position += 4;
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
ret = utility::swapU32(ret);
return ret;
}
Int64 BinaryReader::readInt64()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int64) > m_length)
THROW_IO_EXCEPTION("Position outside stream bounds");
Int64 ret = *(Int64*)(m_data + m_position);
m_position += 8;
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
ret = utility::swap64(ret);
return ret;
}
Uint64 BinaryReader::readUint64()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint64) > m_length)
THROW_IO_EXCEPTION("Position outside stream bounds");
Uint64 ret = *(Uint64*)(m_data + m_position);
m_position += 8;
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
ret = utility::swapU64(ret);
return ret;
}
float BinaryReader::readFloat()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(float) > m_length)
THROW_IO_EXCEPTION("Position outside stream bounds");
float ret = *(float*)(m_data + m_position);
m_position += 4;
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
ret = utility::swapFloat(ret);
return ret;
}
double BinaryReader::readDouble()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(double) > m_length)
THROW_IO_EXCEPTION("Position outside stream bounds");
double ret = *(double*)(m_data + m_position);
m_position += 8;
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
ret = utility::swapDouble(ret);
return ret;
}
bool BinaryReader::readBool()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(bool) > m_length)
THROW_IO_EXCEPTION("Position outside stream bounds");
bool ret = *(bool*)(m_data + m_position);
m_position += 1;
return ret;
}
std::string BinaryReader::readUnicode()
{
if (!m_data)
loadData();
std::string ret;
std::vector<short> tmp;
Uint16 chr = readUint16();
for(;;)
{
if (!chr)
break;
tmp.push_back(chr);
chr = readUint16();
}
utf8::utf16to8(tmp.begin(), tmp.end(), back_inserter(ret));
return ret;
}
std::string BinaryReader::readString()
{
std::string ret = "";
Uint8 chr = readByte();
while (chr != 0)
{
ret += chr;
chr = readByte();
}
return ret;
}
void BinaryReader::setProgressCallback(std::function<void (int)> cb)
{
m_progressCallback = cb;
}
void BinaryReader::loadData()
{
FILE* in;
Uint32 length;
in = fopen(m_filepath.c_str(), "rb");
if (!in)
THROW_FILE_NOT_FOUND_EXCEPTION(m_filepath);
fseek(in, 0, SEEK_END);
length = ftell(in);
fseek(in, 0, SEEK_SET);
#ifdef HW_RVL
m_data = (Uint8*)memalign(32, length);
#else
m_data = new Uint8[length];
#endif
Uint32 done = 0;
Uint32 blocksize = BLOCKSZ;
do
{
if (blocksize > length - done)
blocksize = length - done;
Int32 ret = fread(m_data + done, 1, blocksize, in);
if (ret < 0)
THROW_IO_EXCEPTION("Error reading data from disk");
else if (ret == 0)
break;
done += ret;
if (m_progressCallback)
m_progressCallback((int)((float)(done* 100.f)/length));
} while (done < length);
fclose(in);
m_length = length;
m_position = 0;
m_bitPosition = 0;
}
}
}

505
src/Athena/BinaryWriter.cpp Normal file
View File

@@ -0,0 +1,505 @@
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/BinaryWriter.hpp"
#include "Athena/IOException.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/InvalidDataException.hpp"
#include "Athena/FileNotFoundException.hpp"
#include "utf8.h"
#include <stdio.h>
#include <string.h>
#include <vector>
#include <iostream>
#ifdef HW_RVL
#include <malloc.h>
#endif // HW_RVL
namespace Athena
{
namespace io
{
BinaryWriter::BinaryWriter(Uint8* data, Uint64 length)
: m_data((Uint8*)data),
m_length(length),
m_position(0),
m_bitPosition(0),
m_endian(Endian::LittleEndian),
m_progressCallback(nullptr)
{}
BinaryWriter::BinaryWriter(const std::string& filename, std::function<void(int)> progressFun)
: m_length(0),
m_filepath(filename),
m_position(0),
m_bitPosition(0),
m_endian(Endian::LittleEndian),
m_progressCallback(progressFun)
{
m_length = 0x10;
m_bitPosition = 0;
m_position = 0;
#ifdef HW_RVL
m_data = (Uint8*)memalign(32, m_length);
#else
m_data = new Uint8[m_length];
#endif
if (!m_data)
THROW_IO_EXCEPTION("Could not allocate memory!");
memset(m_data, 0, m_length);
}
BinaryWriter::~BinaryWriter()
{
if (isOpen())
save();
delete[] m_data;
m_data = nullptr;
}
void BinaryWriter::setEndian(Endian endian)
{
m_endian = endian;
}
Endian BinaryWriter::endian() const
{
return m_endian;
}
bool BinaryWriter::isBigEndian() const
{
return (m_endian == Endian::BigEndian);
}
bool BinaryWriter::isLittleEndian() const
{
return (m_endian == Endian::LittleEndian);
}
bool BinaryWriter::isOpen() const
{
return m_data != nullptr;
}
void BinaryWriter::seek(Int64 position, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin::Begin:
if (position < 0)
THROW_IO_EXCEPTION("Position outside stream bounds");
if ((Uint64)position > m_length)
resize(position);
m_position = position;
break;
case SeekOrigin::Current:
if ((((Int64)m_position + position) < 0))
THROW_IO_EXCEPTION("Position outside stream bounds");
if (m_position + position > m_length)
resize(m_position + position);
m_position += position;
break;
case SeekOrigin::End:
if (((Int64)m_length - position) < 0)
THROW_IO_EXCEPTION("Position outside stream bounds");
if ((Uint64)position > m_length)
resize(position);
m_position = m_length - position;
break;
}
}
bool BinaryWriter::atEnd() const
{
return m_position >= m_length;
}
Uint64 BinaryWriter::position() const
{
return m_position;
}
Uint64 BinaryWriter::length() const
{
return m_length;
}
void BinaryWriter::setFilepath(const std::string& filepath)
{
m_filepath = filepath;
}
std::string BinaryWriter::filepath() const
{
return m_filepath;
}
void BinaryWriter::setData(const Uint8* data, Uint64 length)
{
if (m_data)
#ifdef HW_RVL
free(m_data);
#else
delete[] m_data;
#endif
m_data = (Uint8*)data;
m_length = length;
m_position = 0;
m_bitPosition = 0;
}
Uint8* BinaryWriter::data() const
{
Uint8* ret = new Uint8[m_length];
memset(ret, 0, m_length);
memcpy(ret, m_data, m_length);
return ret;
}
void BinaryWriter::save(const std::string& filename)
{
if (filename.empty() && m_filepath.empty())
THROW_INVALID_OPERATION_EXCEPTION("No file specified, cannot save.");
if (!filename.empty())
m_filepath = filename;
FILE* out = fopen(m_filepath.c_str(), "wb");
if (!out)
THROW_FILE_NOT_FOUND_EXCEPTION(m_filepath);
Uint32 done = 0;
Uint32 blocksize = BLOCKSZ;
do
{
if (blocksize > m_length - done)
blocksize = m_length - done;
Int32 ret = fwrite(m_data + done, 1, blocksize, out);
if (ret < 0)
THROW_IO_EXCEPTION("Error writing data to disk");
else if (ret == 0)
break;
done += blocksize;
}while (done < m_length);
fclose(out);
}
void BinaryWriter::seekBit(int bit)
{
if (bit < 0 || bit > 7)
THROW_INVALID_OPERATION_EXCEPTION("bit out of range");
m_bitPosition = bit;
}
void BinaryWriter::writeBit(bool val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
if (m_position + sizeof(Uint8) > m_length)
resize(m_position + sizeof(Uint8));
if (val)
*(Uint8*)(m_data + m_position) |= (1 << m_bitPosition);
else
*(Uint8*)(m_data + m_position) &= ~(1 << m_bitPosition);
m_bitPosition++;
if (m_bitPosition > 7)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
}
void BinaryWriter::writeUByte(Uint8 val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + 1 > m_length)
resize(m_position + 1);
*(Uint8*)(m_data + m_position) = val;
m_position++;
}
void BinaryWriter::writeByte(Int8 val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
writeUByte(val);
}
void BinaryWriter::writeUBytes(Uint8* data, Uint64 length)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (!data)
THROW_INVALID_DATA_EXCEPTION("data cannnot be NULL");
if (m_position + length > m_length)
resize(m_position + length);
memcpy((Int8*)(m_data + m_position), data, length);
m_position += length;
}
void BinaryWriter::writeBytes(Int8* data, Uint64 length)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
writeUBytes((Uint8*)data, length);
}
void BinaryWriter::writeInt16(Int16 val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int16) > m_length)
resize(m_position + sizeof(Int16));
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
val = utility::swap16(val);
*(Int16*)(m_data + m_position) = val;
m_position += sizeof(Int16);
}
void BinaryWriter::writeUint16(Uint16 val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
writeInt16(val);
}
void BinaryWriter::writeInt32(Int32 val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int32) > m_length)
resize(m_position + sizeof(Int32));
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
val = utility::swap32(val);
*(Int32*)(m_data + m_position) = val;
m_position += sizeof(Int32);
}
void BinaryWriter::writeUint32(Uint32 val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
writeInt32(val);
}
void BinaryWriter::writeInt64(Int64 val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int64) > m_length)
resize(m_position + sizeof(Int64));
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
val = utility::swap64(val);
*(Int64*)(m_data + m_position) = val;
m_position += sizeof(Int64);
}
void BinaryWriter::writeUint64(Uint64 val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint64) > m_length)
resize(m_position + sizeof(Uint64));
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
val = utility::swapU64(val);
*(Uint64*)(m_data + m_position) = val;
m_position += sizeof(Uint64);
}
void BinaryWriter::writeFloat(float val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(float) > m_length)
resize(m_position + sizeof(float));
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
val = utility::swapFloat(val);
*(float*)(m_data + m_position) = val;
m_position += sizeof(float);
}
void BinaryWriter::writeDouble(double val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(double) > m_length)
resize(m_position + sizeof(double));
if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian()))
val = utility::swapDouble(val);
*(double*)(m_data + m_position)= val;
m_position += sizeof(double);
}
void BinaryWriter::writeBool(bool val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(bool) > m_length)
resize(m_position + sizeof(bool));
*(bool*)(m_data + m_position) = val;
m_position += sizeof(bool);
}
void BinaryWriter::writeUnicode(const std::string& str)
{
std::string tmpStr = "\xEF\xBB\xBF" + str;
std::vector<short> tmp;
utf8::utf8to16(tmpStr.begin(), tmpStr.end(), back_inserter(tmp));
for (Uint16 chr : tmp)
{
if (chr != 0xFEFF)
writeInt16(chr);
}
writeInt16(0);
}
void BinaryWriter::writeString(const std::string& str)
{
for (Uint8 c : str)
{
writeUByte(c);
if (c == '\0')
break;
}
writeUByte(0);
}
void BinaryWriter::setProgressCallback(std::function<void (int)> cb)
{
m_progressCallback = cb;
}
void BinaryWriter::resize(Uint64 newSize)
{
if (newSize < m_length)
THROW_INVALID_OPERATION_EXCEPTION("Stream::resize() -> New size cannot be less to the old size.");
// Allocate and copy new buffer
#ifdef HW_RVL
Uint8* newArray = (Uint8*)memalign(32, newSize);
#else
Uint8* newArray = new Uint8[newSize];
#endif
memset(newArray, 0, newSize);
memcpy(newArray, m_data, m_length);
// Delete the old one
#ifdef HW_RVL
free(m_data);
#else
delete[] m_data;
#endif
// Swap the pointer and size out for the new ones.
m_data = newArray;
m_length = newSize;
}
} // io
} // Athena

View File

@@ -1,9 +1,24 @@
#include "Checksums.hpp"
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/Checksums.hpp"
#include <iostream>
#include <iomanip>
namespace zelda
namespace Athena
{
namespace Checksums
{

View File

@@ -13,13 +13,13 @@
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "Compression.hpp"
#include "Exception.hpp"
#include "Athena/Compression.hpp"
#include "Athena/Exception.hpp"
#include "lzo.h"
#include <iostream>
#include <zlib.h>
namespace zelda
namespace Athena
{
namespace io
{

333
src/Athena/FileReader.cpp Normal file
View File

@@ -0,0 +1,333 @@
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/FileReader.hpp"
#include "Athena/FileNotFoundException.hpp"
#include "Athena/InvalidDataException.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/IOException.hpp"
#include "utf8.h"
namespace Athena
{
namespace io
{
FileReader::FileReader(const std::string& filename)
: m_filename(filename),
m_fileHandle(NULL),
m_endian(Endian::LittleEndian),
m_bitValid(false)
{
open();
}
FileReader::~FileReader()
{
close();
}
std::string FileReader::filename() const
{
return m_filename;
}
void FileReader::setEndian(Endian endian)
{
m_endian = endian;
}
Endian FileReader::endian() const
{
return m_endian;
}
bool FileReader::isBigEndian() const
{
return (m_endian == Endian::BigEndian);
}
bool FileReader::isLittleEndian() const
{
return (m_endian == Endian::LittleEndian);
}
void FileReader::open()
{
m_fileHandle = fopen(m_filename.c_str(), "rb");
if (!m_fileHandle)
THROW_FILE_NOT_FOUND_EXCEPTION(m_filename);
// ensure we're at the beginning of the file
rewind(m_fileHandle);
}
void FileReader::close()
{
if (!m_fileHandle)
THROW_INVALID_OPERATION_EXCEPTION("Cannot close an unopened stream");
fclose(m_fileHandle);
m_fileHandle = NULL;
return;
}
bool FileReader::isOpen() const
{
return m_fileHandle != NULL;
}
void FileReader::seek(Int64 pos, SeekOrigin origin)
{
if (fseeko64(m_fileHandle, pos, (int)origin) != 0)
THROW_INVALID_OPERATION_EXCEPTION("Unable to seek in file");
}
bool FileReader::atEnd() const
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open");
return feof(m_fileHandle) != 0;
}
Uint64 FileReader::position() const
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open");
return ftello64(m_fileHandle);
}
Uint64 FileReader::length() const
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open");
return utility::fileSize(m_fileHandle);
}
void FileReader::seekBit(int bit)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open");
if (bit < 0 || bit > 7)
THROW_INVALID_OPERATION_EXCEPTION("bit out of range");
m_bitShift = bit;
}
bool FileReader::readBit()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File is not open for reading");
if (!m_bitValid)
{
int size = fread(&m_currentByte, 1, 1, m_fileHandle);
if (size != sizeof(Uint8))
THROW_IO_EXCEPTION("Error reading from file.");
m_bitShift = 0;
m_bitValid = true;
}
Uint8 flag = (1 << m_bitShift);
m_bitShift++;
if (m_bitShift > 7)
m_bitValid = false;
return ((m_currentByte & flag) == flag);
}
Uint8 FileReader::readUByte()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
m_bitValid = false;
Uint8 val = 0;
fread(&val, 1, 1, m_fileHandle);
return val;
}
Int8 FileReader::readByte()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
return (Int8)readUByte();
}
Uint8* FileReader::readUBytes(Uint64 len)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
m_bitValid = false;
Uint8* val = new Uint8[len];
fread(val, 1, len, m_fileHandle);
return val;
}
Int8* FileReader::readBytes(Uint64 len)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
return (Int8*)readUBytes(len);
}
Uint16 FileReader::readUint16()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
m_bitValid = false;
Uint16 val;
fread(&val, 1, sizeof(Uint16), m_fileHandle);
if ((utility::isSystemBigEndian() && !isBigEndian()) || (!utility::isSystemBigEndian() && isBigEndian()))
utility::swapU16(val);
return val;
}
Int16 FileReader::readInt16()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
return (Int16)readUint16();
}
Uint32 FileReader::readUint32()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
m_bitValid = false;
Uint32 val;
fread(&val, 1, sizeof(Uint32), m_fileHandle);
if ((utility::isSystemBigEndian() && !isBigEndian()) || (!utility::isSystemBigEndian() && isBigEndian()))
utility::swapU64(val);
return val;
}
Int32 FileReader::readInt32()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
return (Int32)readUint32();
}
Uint64 FileReader::readUint64()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
m_bitValid = false;
Uint64 val;
fread(&val, 1, sizeof(Uint64), m_fileHandle);
if ((utility::isSystemBigEndian() && !isBigEndian()) || (!utility::isSystemBigEndian() && isBigEndian()))
utility::swapU64(val);
return val;
}
Int64 FileReader::readInt64()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
return (Int64)readUint64();
}
double FileReader::readDouble()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
m_bitValid = false;
double val;
fread(&val, 1, sizeof(double), m_fileHandle);
if ((utility::isSystemBigEndian() && !isBigEndian()) || (!utility::isSystemBigEndian() && isBigEndian()))
utility::swapDouble(val);
return val;
}
float FileReader::readFloat()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
m_bitValid = false;
float val;
fread(&val, 1, sizeof(float), m_fileHandle);
if ((utility::isSystemBigEndian() && !isBigEndian()) || (!utility::isSystemBigEndian() && isBigEndian()))
utility::swapFloat(val);
return val;
}
bool FileReader::readBool()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
return (readByte() != 0);
}
std::string FileReader::readString()
{
std::string ret = "";
Uint8 chr = readByte();
while (chr != 0)
{
ret += chr;
chr = readByte();
}
return ret;
}
std::string FileReader::readUnicode()
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for reading");
std::string ret;
std::vector<short> tmp;
for(;;)
{
short chr = readUint16();
if (chr)
tmp.push_back(chr);
else
break;
};
utf8::utf16to8(tmp.begin(), tmp.end(), back_inserter(ret));
return ret;
}
} // io
} // Athena

298
src/Athena/FileWriter.cpp Normal file
View File

@@ -0,0 +1,298 @@
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/FileWriter.hpp"
#include "Athena/FileNotFoundException.hpp"
#include "Athena/InvalidDataException.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/IOException.hpp"
#include "utf8.h"
namespace Athena
{
namespace io
{
FileWriter::FileWriter(const std::string& filename)
: m_filename(filename),
m_fileHandle(NULL),
m_endian(Endian::LittleEndian),
m_bytePosition(0),
m_bitShift(0),
m_bitValid(false)
{
open();
}
FileWriter::~FileWriter()
{
if (isOpen())
close();
}
void FileWriter::setEndian(Endian endian)
{
m_endian = endian;
}
Endian FileWriter::endian() const
{
return m_endian;
}
bool FileWriter::isBigEndian() const
{
return (m_endian == Endian::BigEndian);
}
bool FileWriter::isLittleEndian() const
{
return (m_endian == Endian::LittleEndian);
}
void FileWriter::open()
{
m_fileHandle = fopen(m_filename.c_str(), "w+b");
if (!m_fileHandle)
THROW_FILE_NOT_FOUND_EXCEPTION(m_filename);
// ensure we're at the beginning of the file
rewind(m_fileHandle);
}
void FileWriter::close()
{
if (!m_fileHandle)
THROW_INVALID_OPERATION_EXCEPTION("Cannot close an unopened stream");
fclose(m_fileHandle);
m_fileHandle = NULL;
return;
}
bool FileWriter::isOpen() const
{
return m_fileHandle != NULL;
}
void FileWriter::seek(Int64 pos, SeekOrigin origin)
{
if (fseeko64(m_fileHandle, pos, (int)origin) != 0)
THROW_IO_EXCEPTION("Unable to seek in file");
}
bool FileWriter::atEnd() const
{
return feof(m_fileHandle) != 0;
}
Uint64 FileWriter::position() const
{
return ftello64(m_fileHandle);
}
Uint64 FileWriter::length() const
{
return utility::fileSize(m_fileHandle);
}
void FileWriter::writeBit(bool val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
if (!m_bitValid)
{
m_bitValid = true;
m_bitShift = 0;
m_bytePosition = ftello64(m_fileHandle);
}
if (val)
m_currentByte |= (1 << m_bitShift++);
else
m_currentByte &= ~(1 << m_bitShift++);
if (m_bitShift > 7)
m_bitValid = false;
fseeko64(m_fileHandle, m_bytePosition, (int)SeekOrigin::Begin);
if (fwrite(&m_currentByte, 1, 1, m_fileHandle) != sizeof(Int8))
THROW_IO_EXCEPTION("Unable to data to file");
}
void FileWriter::seekBit(int bit)
{
if (bit < 0 || bit > 7)
THROW_INVALID_OPERATION_EXCEPTION("bit must be >= 0 and <= 7");
m_bitShift = bit;
m_bitValid = true;
}
void FileWriter::writeUByte(Uint8 val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
m_bitValid = false;
if (fwrite(&val, 1, sizeof(Uint8), m_fileHandle) != sizeof(Uint8))
THROW_IO_EXCEPTION("Unable to write to stream");
}
void FileWriter::writeByte(Int8 val)
{
writeUByte(val);
}
void FileWriter::writeUBytes(Uint8* data, Uint64 len)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
m_bitValid = false;
if (fwrite(data, 1, len, m_fileHandle) != len)
THROW_IO_EXCEPTION("Unable to write to stream");
}
void FileWriter::writeBytes(Int8* data, Uint64 len)
{
writeUBytes((Uint8*)data, len);
}
void FileWriter::writeUint16(Uint16 val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
m_bitValid = false;
if ((utility::isSystemBigEndian() && !isBigEndian()) || (!utility::isSystemBigEndian() && isBigEndian()))
utility::swapU16(val);
if (fwrite(&val, 1, sizeof(Uint16), m_fileHandle) != sizeof(Uint16))
THROW_IO_EXCEPTION("Unable to write to stream");
}
void FileWriter::writeInt16(Int16 val)
{
writeUint16(val);
}
void FileWriter::writeUint32(Uint32 val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
m_bitValid = false;
if ((utility::isSystemBigEndian() && !isBigEndian()) || (!utility::isSystemBigEndian() && isBigEndian()))
utility::swapU32(val);
if (fwrite(&val, 1, sizeof(Uint32), m_fileHandle) != sizeof(Uint32))
THROW_IO_EXCEPTION("Unable to write to stream");
}
void FileWriter::writeInt32(Int32 val)
{
writeUint32(val);
}
void FileWriter::writeUint64(Uint64 val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
m_bitValid = false;
if ((utility::isSystemBigEndian() && !isBigEndian()) || (!utility::isSystemBigEndian() && isBigEndian()))
utility::swapU32(val);
if (fwrite(&val, 1, sizeof(Uint64), m_fileHandle) != sizeof(Uint64))
THROW_IO_EXCEPTION("Unable to write to stream");
}
void FileWriter::writeInt64(Int64 val)
{
writeUint64(val);
}
void FileWriter::writeDouble(double val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
m_bitValid = false;
if ((utility::isSystemBigEndian() && !isBigEndian()) || (!utility::isSystemBigEndian() && isBigEndian()))
utility::swapDouble(val);
if (fwrite(&val, 1, sizeof(double), m_fileHandle) != sizeof(double))
THROW_IO_EXCEPTION("Unable to write to stream");
}
void FileWriter::writeFloat(float val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
m_bitValid = false;
if ((utility::isSystemBigEndian() && !isBigEndian()) || (!utility::isSystemBigEndian() && isBigEndian()))
utility::swapFloat(val);
if (fwrite(&val, 1, sizeof(float), m_fileHandle) != sizeof(float))
THROW_IO_EXCEPTION("Unable to write to stream");
}
void FileWriter::writeBool(bool val)
{
writeByte(val);
}
void FileWriter::writeString(const std::string& val)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
m_bitValid = false;
char term = '\0';
if (fwrite(val.c_str(), 1, val.length(), m_fileHandle) != val.length())
THROW_IO_EXCEPTION("Unable to write to stream");
if (fwrite(&term, 1, 1, m_fileHandle) != 1)
THROW_IO_EXCEPTION("Unable to write to stream");
}
void FileWriter::writeUnicode(const std::string& str)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
std::string tmpStr = "\xEF\xBB\xBF" + str;
std::vector<short> tmp;
utf8::utf8to16(tmpStr.begin(), tmpStr.end(), back_inserter(tmp));
for (Uint16 chr : tmp)
{
if (chr != 0xFEFF)
writeInt16(chr);
}
}
}
} // Athena

48
src/Athena/Global.cpp Normal file
View File

@@ -0,0 +1,48 @@
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/Global.hpp"
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::End:
os << "End";
break;
}
return os;
}
std::ostream& operator<<(std::ostream& os, const Athena::Endian& endian)
{
switch(endian)
{
case Athena::Endian::LittleEndian:
os << "LittleEndian";
break;
case Athena::Endian::BigEndian:
os << "BigEndian";
break;
}
return os;
}

View File

@@ -1,21 +1,21 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "MCFile.hpp"
#include "Athena/MCFile.hpp"
namespace zelda
namespace Athena
{
MCFile::MCFile()

View File

@@ -1,21 +1,21 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "MCFileReader.hpp"
#include "Athena/MCFileReader.hpp"
namespace zelda
namespace Athena
{
namespace io

View File

@@ -1,21 +1,21 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "MCFileWriter.hpp"
#include "Athena/MCFileWriter.hpp"
namespace zelda
namespace Athena
{
namespace io
{

View File

@@ -0,0 +1,71 @@
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/SkywardSwordFile.hpp"
#include "Athena/SkywardSwordQuest.hpp"
#include "Athena/InvalidOperationException.hpp"
namespace Athena
{
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);
}
SkywardSwordQuest *SkywardSwordFile::quest(Uint32 id)
{
if (id > m_quests.size() - 1)
THROW_INVALID_OPERATION_EXCEPTION("index out of range");
return m_quests[id];
}
std::vector<SkywardSwordQuest*> SkywardSwordFile::questList() const
{
return m_quests;
}
void SkywardSwordFile::setRegion(Region region)
{
m_region = region;
}
Region SkywardSwordFile::region() const
{
return m_region;
}
} // zelda

View File

@@ -0,0 +1,84 @@
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/SkywardSwordFileReader.hpp"
#include "Athena/SkywardSwordFile.hpp"
#include "Athena/SkywardSwordQuest.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/InvalidDataException.hpp"
#include <iostream>
namespace Athena
{
namespace io
{
SkywardSwordFileReader::SkywardSwordFileReader(Uint8* data, Uint64 length)
: base(data, length)
{
base::setEndian(Endian::BigEndian);
}
SkywardSwordFileReader::SkywardSwordFileReader(const std::string& filename)
: base(filename)
{
base::setEndian(Endian::BigEndian);
}
SkywardSwordFile* SkywardSwordFileReader::read()
{
SkywardSwordFile* file = NULL;
try
{
if (base::length() != 0xFBE0)
THROW_INVALID_DATA_EXCEPTION("File not the expected size of 0xFBE0");
Uint32 magic = base::readUint32();
if (magic != SkywardSwordFile::USMagic && magic != SkywardSwordFile::JAMagic && magic != SkywardSwordFile::EUMagic)
THROW_INVALID_DATA_EXCEPTION("Not a valid Skyward Sword save file");
base::seek(0x01C, SeekOrigin::Begin);
Uint32 headerSize = base::readUint32(); // Seems to be (headerSize - 1)
if (headerSize != 0x1D)
THROW_INVALID_DATA_EXCEPTION("Invalid header size, Corrupted data?");
// 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((Uint8*)base::readBytes(0x53C0), 0x53C0);
Uint64 pos = base::position();
// seek to the skip data for this particular quest
base::seek(0xFB60 + (i * 0x24), SeekOrigin::Begin);
q->setSkipData(base::readUBytes(0x24));
base::seek(pos, SeekOrigin::Begin);
file->addQuest(q);
}
}
catch(...)
{
delete file;
file = NULL;
throw;
}
return file;
}
} // io
} // zelda

View File

@@ -0,0 +1,75 @@
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/SkywardSwordFileWriter.hpp"
#include "Athena/SkywardSwordFile.hpp"
#include "Athena/SkywardSwordQuest.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/InvalidDataException.hpp"
namespace Athena
{
namespace io
{
SkywardSwordFileWriter::SkywardSwordFileWriter(Uint8 *data, Uint64 len)
: base(data, len)
{
base::setEndian(Endian::BigEndian);
}
SkywardSwordFileWriter::SkywardSwordFileWriter(const std::string &filename)
: base(filename)
{
base::setEndian(Endian::BigEndian);
}
void SkywardSwordFileWriter::write(SkywardSwordFile *file)
{
if (!file)
THROW_INVALID_OPERATION_EXCEPTION("file cannot be NULL");
Uint32 magic = (file->region() == Region::NTSC ? SkywardSwordFile::USMagic :
(file->region() == Region::NTSCJ ? SkywardSwordFile::JAMagic : SkywardSwordFile::EUMagic));
base::writeUint32(magic);
base::seek(0x1C, SeekOrigin::Begin);
base::writeUint32(0x1D);
std::vector<SkywardSwordQuest*> quests = file->questList();
int i = 0;
for (SkywardSwordQuest* q : quests)
{
if (q->length() != 0x53C0)
THROW_INVALID_DATA_EXCEPTION("q->data() not 0x53C0 bytes in length");
if (q->skipLength() != 0x24)
THROW_INVALID_DATA_EXCEPTION("q->skipData() not 0x24 bytes in length");
// Write the save data
base::writeUBytes(q->data(), q->length());
Uint64 pos = base::position();
// Write the slots skip data
base::seek(0xFB60 + (i * 0x24), SeekOrigin::Begin);
base::writeUBytes(q->skipData(), q->skipLength());
base::seek(pos, SeekOrigin::Begin);
i++;
}
// write those padding bytes
base::seek(0xFBE0, SeekOrigin::Begin);
save();
}
} // io
} // zelda

View File

@@ -0,0 +1,49 @@
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/SkywardSwordQuest.hpp"
namespace Athena
{
SkywardSwordQuest::SkywardSwordQuest(Uint8 *data, Uint32 len)
: ZQuestFile(ZQuestFile::SS, Endian::BigEndian, data, len),
m_skipData(nullptr),
m_skipLength(0)
{
}
void SkywardSwordQuest::setSkipData(const Uint8 *data, Uint32 len)
{
if (m_skipData)
{
delete[] m_skipData;
m_skipData = nullptr;
}
m_skipData = (Uint8*)data;
m_skipLength = len;
}
Uint8 *SkywardSwordQuest::skipData() const
{
return m_skipData;
}
Uint32 SkywardSwordQuest::skipLength() const
{
return m_skipLength;
}
} // zelda

View File

@@ -1,13 +1,28 @@
#include "Sprite.hpp"
#include "SpriteFrame.hpp"
#include "SpriteFile.hpp"
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/Sprite.hpp"
#include "Athena/SpriteFrame.hpp"
#include "Athena/SpriteFile.hpp"
#include <algorithm>
#ifdef LIBZELDA_USE_QT
#include <QVector>
#endif
namespace zelda
namespace Athena
{
namespace Sakura
{

View File

@@ -1,9 +1,24 @@
#include "SpriteFile.hpp"
#include "Sprite.hpp"
#include "utility.hpp"
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/SpriteFile.hpp"
#include "Athena/Sprite.hpp"
#include "Athena/Utility.hpp"
#include <iostream>
namespace zelda
namespace Athena
{
namespace Sakura
{
@@ -190,7 +205,7 @@ void SpriteFile::addSprite(Sprite* sprite)
{
#ifndef LIBZELDA_USE_QT
std::string name(sprite->name());
zelda::utility::tolower(name);
Athena::utility::tolower(name);
if (m_sprites.find(name) != m_sprites.end())
return;
#else
@@ -206,7 +221,7 @@ void SpriteFile::addSprite(Sprite* sprite)
void SpriteFile::removeSprite(const std::string& name)
{
std::string tmpName(name);
zelda::utility::tolower(tmpName);
Athena::utility::tolower(tmpName);
std::unordered_map<std::string, Sprite*>::iterator iterator = m_sprites.find(tmpName);
if (iterator != m_sprites.end())
m_sprites.erase(iterator);
@@ -254,7 +269,7 @@ void SpriteFile::setSprites(QMap<QString, Sprite *> sprites)
Sprite* SpriteFile::sprite(const std::string& name)
{
std::string nameLow(name);
zelda::utility::tolower(nameLow);
Athena::utility::tolower(nameLow);
if (m_sprites.find(nameLow) == m_sprites.end())
return NULL;

View File

@@ -1,13 +1,29 @@
#include "SpriteFileReader.hpp"
#include "SpriteFile.hpp"
#include "Sprite.hpp"
#include "SpritePart.hpp"
#include "SpriteFrame.hpp"
#include "InvalidOperationException.hpp"
#include "IOException.hpp"
#include "utility.hpp"
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
namespace zelda
#include "Athena/SpriteFileReader.hpp"
#include "Athena/SpriteFile.hpp"
#include "Athena/Sprite.hpp"
#include "Athena/SpritePart.hpp"
#include "Athena/SpriteFrame.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/InvalidDataException.hpp"
#include "Athena/IOException.hpp"
#include "Athena/Utility.hpp"
namespace Athena
{
namespace io
{
@@ -27,29 +43,29 @@ Sakura::SpriteFile* SpriteFileReader::readFile()
Sakura::SpriteFile* ret = NULL;
try
{
Uint32 magic = base::readUInt32();
Uint32 magic = base::readUint32();
if (magic != Sakura::SpriteFile::Magic)
throw zelda::error::InvalidOperationException("Not a valid Sakura Sprite container");
THROW_INVALID_DATA_EXCEPTION("Not a valid Sakura Sprite container");
Uint32 version = base::readUInt32();
Uint32 version = base::readUint32();
// TODO: Make this more verbose
if (version != Sakura::SpriteFile::Version)
throw zelda::error::InvalidOperationException("Unsupported version");
THROW_INVALID_DATA_EXCEPTION("Unsupported version");
// After reading in the magic and version we need to load some
// metadata about the file.
// Such as the texture count, it's dimensions, and it's origin.
// After that we have the number of sprites contained in this
// sprite container.
Uint16 textureCount = base::readUInt16(); // Having it as a Uint16 gives us the ability to have up to 65536 different states
Uint16 textureCount = base::readUint16(); // Having it as a Uint16 gives us the ability to have up to 65536 different states
// This is probably overkill, but it's better safe than sorry.
Uint32 width = base::readUInt32();
Uint32 height = base::readUInt32();
Uint32 width = base::readUint32();
Uint32 height = base::readUint32();
float originX = base::readFloat();
float originY = base::readFloat();
Uint16 spriteCount = base::readUInt16();
Uint16 spriteCount = base::readUint16();
// Lets go ahead and create or new container.
ret = new Sakura::SpriteFile(width, height, originX, originY);
@@ -59,7 +75,7 @@ Sakura::SpriteFile* SpriteFileReader::readFile()
// to migrate this code to Big Endian based systems, such as the wii
// which require data to be 32 byte aligned, or it causes some issues.
// It's also convenient to have this, for later expansion.
Uint32 reserved = base::readUInt32();
Uint32 reserved = base::readUint32();
UNUSED(reserved);
// Next we have to load the textures
@@ -104,13 +120,13 @@ Sakura::SpriteFile* SpriteFileReader::readFile()
QString name = QString::fromStdString(base::readString());
#endif
sprite->setName(name);
Uint16 frameCount = base::readUInt16();
Uint16 stateCount = base::readUInt16();
Uint16 frameCount = base::readUint16();
Uint16 stateCount = base::readUint16();
// Each state id corresponds to a texture held in the parent class
std::vector<int> stateIds;
for (int j = 0; j < stateCount; j++)
stateIds.push_back(base::readUInt16());
stateIds.push_back(base::readUint16());
sprite->setStateIds(stateIds);
@@ -132,7 +148,7 @@ Sakura::SpriteFile* SpriteFileReader::readFile()
{
Sakura::SpriteFrame* frame = new Sakura::SpriteFrame(sprite);
frame->setFrameTime(base::readFloat());
Uint16 partCount = base::readUInt16();
Uint16 partCount = base::readUint16();
#ifndef LIBZELDA_USE_QT
@@ -157,8 +173,8 @@ Sakura::SpriteFile* SpriteFileReader::readFile()
float texXOff = base::readFloat();
float texYOff = base::readFloat();
part->setTextureOffset(texXOff, texYOff);
Uint32 width = base::readUInt32();
Uint32 height = base::readUInt32();
Uint32 width = base::readUint32();
Uint32 height = base::readUint32();
part->setSize(width, height);
bool flippedH = base::readBool();
part->setFlippedHorizontally(flippedH);
@@ -176,7 +192,7 @@ Sakura::SpriteFile* SpriteFileReader::readFile()
if (sprite->name() != std::string())
{
std::string nameLow(sprite->name());
zelda::utility::tolower(nameLow);
Athena::utility::tolower(nameLow);
sprites[nameLow] = sprite;
}
#else
@@ -184,7 +200,7 @@ Sakura::SpriteFile* SpriteFileReader::readFile()
sprites[sprite->name().toLower()] = sprite;
#endif
else
throw zelda::error::IOException("SSpriteFileReader::readFile -> Sprite names cannot be empty");
THROW_IO_EXCEPTION("Sprite names cannot be empty");
}
ret->setSprites(sprites);

View File

@@ -1,11 +1,27 @@
#include "SpriteFileWriter.hpp"
#include "SpriteFile.hpp"
#include "Sprite.hpp"
#include "SpritePart.hpp"
#include "SpriteFrame.hpp"
#include "InvalidOperationException.hpp"
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
namespace zelda
#include "Athena/SpriteFileWriter.hpp"
#include "Athena/SpriteFile.hpp"
#include "Athena/Sprite.hpp"
#include "Athena/SpritePart.hpp"
#include "Athena/SpriteFrame.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/InvalidDataException.hpp"
namespace Athena
{
namespace io
{
@@ -22,19 +38,19 @@ SpriteFileWriter::SpriteFileWriter(const std::string& filepath)
void SpriteFileWriter::writeFile(Sakura::SpriteFile* file)
{
if (!file)
throw zelda::error::InvalidOperationException("SSpriteFileWriter::writeFile -> file cannot be NULL");
THROW_INVALID_OPERATION_EXCEPTION("SSpriteFileWriter::writeFile -> file cannot be NULL");
base::writeUInt32(Sakura::SpriteFile::Magic);
base::writeUInt32(Sakura::SpriteFile::Version);
base::writeUint32(Sakura::SpriteFile::Magic);
base::writeUint32(Sakura::SpriteFile::Version);
base::writeUInt16(file->textureCount());
base::writeUInt32(file->width());
base::writeUInt32(file->height());
base::writeUint16(file->textureCount());
base::writeUint32(file->width());
base::writeUint32(file->height());
base::writeFloat(file->originX());
base::writeFloat(file->originY());
base::writeUInt16(file->spriteCount());
base::writeUint16(file->spriteCount());
base::writeUInt32(0xFFFFFFFF);
base::writeUint32(0xFFFFFFFF);
for (Sakura::STexture* texture : file->textures())
{
@@ -53,16 +69,16 @@ void SpriteFileWriter::writeFile(Sakura::SpriteFile* file)
base::writeString(sprite->name().toStdString());
#endif
base::writeUInt16(sprite->frameCount());
base::writeUInt16(sprite->stateCount());
base::writeUint16(sprite->frameCount());
base::writeUint16(sprite->stateCount());
for (int id : sprite->stateIds())
base::writeUInt16(id);
base::writeUint16(id);
for (Sakura::SpriteFrame* frame : sprite->frames())
{
base::writeFloat(frame->frameTime());
base::writeUInt16(frame->partCount());
base::writeUint16(frame->partCount());
for (Sakura::SpritePart* part: frame->parts())
{
#ifndef LIBZELDA_USE_QT
@@ -76,15 +92,15 @@ void SpriteFileWriter::writeFile(Sakura::SpriteFile* file)
base::writeFloat(part->offset().y);
base::writeFloat(part->textureOffset().x);
base::writeFloat(part->textureOffset().y);
base::writeUInt32(part->size().x);
base::writeUInt32(part->size().y);
base::writeUint32(part->size().x);
base::writeUint32(part->size().y);
#else
base::writeFloat(part->offset().x());
base::writeFloat(part->offset().y());
base::writeFloat(part->textureOffset().x());
base::writeFloat(part->textureOffset().y());
base::writeUInt32(part->size().width());
base::writeUInt32(part->size().height());
base::writeUint32(part->size().width());
base::writeUint32(part->size().height());
#endif
base::writeBool(part->flippedHorizontally());
base::writeBool(part->flippedVertically());

View File

@@ -1,8 +1,23 @@
#include "SpriteFrame.hpp"
#include "SpritePart.hpp"
#include "Sprite.hpp"
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
namespace zelda
#include "Athena/SpriteFrame.hpp"
#include "Athena/SpritePart.hpp"
#include "Athena/Sprite.hpp"
namespace Athena
{
namespace Sakura
{

View File

@@ -1,9 +1,24 @@
#include "SpritePart.hpp"
#include "SpritePart.hpp"
#include "Sprite.hpp"
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/SpritePart.hpp"
#include "Athena/SpritePart.hpp"
#include "Athena/Sprite.hpp"
#include <algorithm>
namespace zelda
namespace Athena
{
namespace Sakura
{

View File

@@ -1,19 +1,19 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "utility.hpp"
#include "Athena/Utility.hpp"
#include <iostream>
#include <string.h>
#include <stdlib.h>
@@ -21,12 +21,12 @@
#include <algorithm>
#include <cstdarg>
#include <iterator>
#include <cstdio>
namespace zelda
namespace Athena
{
namespace utility
{
bool isEmpty(Int8* buf, Uint32 size)
{
return buf[0] == 0 && !memcmp(buf, buf + 1, size - 1);
@@ -62,13 +62,13 @@ Uint64 swapU64(Uint64 val)
Int64 swap64(Int64 val)
{
return ((Int64)((((Int64)(val) & 0xFF00000000000000ULL) >> 56) |
(((Int64)(val) & 0x00FF000000000000ULL) >> 40) |
(((Int64)(val) & 0x0000FF0000000000ULL) >> 24) |
(((Int64)(val) & 0x000000FF00000000ULL) >> 8) |
(((Int64)(val) & 0x00000000FF000000ULL) << 8) |
(((Int64)(val) & 0x0000000000FF0000ULL) << 24) |
(((Int64)(val) & 0x000000000000FF00ULL) << 40) |
(((Int64)(val) & 0x00000000000000FFULL) << 56)));
(((Int64)(val) & 0x00FF000000000000ULL) >> 40) |
(((Int64)(val) & 0x0000FF0000000000ULL) >> 24) |
(((Int64)(val) & 0x000000FF00000000ULL) >> 8) |
(((Int64)(val) & 0x00000000FF000000ULL) << 8) |
(((Int64)(val) & 0x0000000000FF0000ULL) << 24) |
(((Int64)(val) & 0x000000000000FF00ULL) << 40) |
(((Int64)(val) & 0x00000000000000FFULL) << 56)));
}
bool isSystemBigEndian()
@@ -223,6 +223,14 @@ int countChar(const std::string& str, const char chr, int* lastOccur)
return ret;
}
Uint64 fileSize(FILE* f)
{
Uint64 oldPos = ftello64(f);
fseeko64(f, 0, SEEK_END);
Uint64 size = ftello64(f);
fseeko64(f, oldPos, SEEK_SET);
return size;
}
} // utility
} // zelda
} // Athena

View File

@@ -1,25 +1,25 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "WiiBanner.hpp"
#include "WiiImage.hpp"
#include "Athena/WiiBanner.hpp"
#include "Athena/WiiImage.hpp"
#include <utility.hpp>
#include "Athena/Utility.hpp"
#include <string.h>
namespace zelda
namespace Athena
{
WiiBanner::WiiBanner() :

View File

@@ -1,22 +1,22 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "WiiFile.hpp"
#include "Athena/WiiFile.hpp"
namespace zelda
namespace Athena
{
//! TODO: Remove this?

View File

@@ -1,24 +1,24 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "WiiImage.hpp"
#include "utility.hpp"
#include "Athena/WiiImage.hpp"
#include "Athena/Utility.hpp"
#include <string.h>
#include <stdlib.h>
namespace zelda
namespace Athena
{
WiiImage::WiiImage(Uint32 width, Uint32 height, Uint8* data) :

View File

@@ -1,26 +1,26 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "WiiSave.hpp"
#include "WiiFile.hpp"
#include "WiiBanner.hpp"
#include "BinaryReader.hpp"
#include "BinaryWriter.hpp"
#include "Athena/WiiSave.hpp"
#include "Athena/WiiFile.hpp"
#include "Athena/WiiBanner.hpp"
#include "Athena/BinaryReader.hpp"
#include "Athena/BinaryWriter.hpp"
#include "Athena/Utility.hpp"
#include "aes.h"
#include "ec.h"
#include "utility.hpp"
#include "md5.h"
#include "sha1.h"
@@ -32,7 +32,7 @@
#include <iomanip>
namespace zelda
namespace Athena
{
WiiSave::WiiSave()

View File

@@ -1,54 +1,51 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "WiiSaveReader.hpp"
#include "WiiSave.hpp"
#include "WiiFile.hpp"
#include "WiiImage.hpp"
#include "WiiBanner.hpp"
#include "Athena/WiiSaveReader.hpp"
#include "Athena/WiiSave.hpp"
#include "Athena/WiiFile.hpp"
#include "Athena/WiiImage.hpp"
#include "Athena/WiiBanner.hpp"
#include "Athena/Utility.hpp"
#include "Athena/IOException.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/InvalidDataException.hpp"
#include "md5.h"
#include "aes.h"
#include "ec.h"
#include "sha1.h"
#include <iostream>
#include <iomanip>
#include <utility.hpp>
#include <IOException.hpp>
#include <InvalidOperationException.hpp>
#include <string.h>
namespace zelda
namespace Athena
{
namespace io
{
const Uint8 SD_KEY[16] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08, 0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d};
const Uint8 SD_IV[16] = {0x21, 0x67, 0x12, 0xe6, 0xaa, 0x1f, 0x68, 0x9f, 0x95, 0xc5, 0xa2, 0x23, 0x24, 0xdc, 0x6a, 0x98};
const Uint8 MD5_BLANKER[16] = {0x0e, 0x65, 0x37, 0x81, 0x99, 0xbe, 0x45, 0x17, 0xab, 0x06, 0xec, 0x22, 0x45, 0x1a, 0x57, 0x93};
WiiSaveReader::WiiSaveReader(const Uint8* data, Uint64 length)
: base(data, length)
{
setEndianess(BigEndian);
setEndian(Endian::BigEndian);
}
WiiSaveReader::WiiSaveReader(const std::string& filename)
: base(filename)
{
setEndianess(BigEndian);
setEndian(Endian::BigEndian);
}
WiiSave* WiiSaveReader::readSave()
@@ -57,32 +54,32 @@ WiiSave* WiiSaveReader::readSave()
try
{
if (length() < 0xF0C0)
throw error::InvalidOperationException("WiiSaveReader::readSave -> Not a valid WiiSave");
THROW_INVALID_DATA_EXCEPTION("Not a valid WiiSave");
WiiBanner* banner = this->readBanner();
if (!banner)
throw error::InvalidOperationException("WiiSaveReader::readSave -> Invalid banner");
THROW_INVALID_DATA_EXCEPTION("Invalid banner");
ret->setBanner(banner);
Uint32 bkVer = base::readUInt32();
Uint32 bkVer = base::readUint32();
if (bkVer != 0x00000070)
throw error::InvalidOperationException("WiiSaveReader::readSave -> Invalid BacKup header size");
THROW_INVALID_DATA_EXCEPTION("Invalid BacKup header size");
Uint32 bkMagic = base::readUInt32();
Uint32 bkMagic = base::readUint32();
bkMagic = bkMagic;
if (bkMagic != 0x426B0001)
throw error::InvalidOperationException("WiiSaveReader::readSave -> Invalid BacKup header magic");
THROW_INVALID_DATA_EXCEPTION("Invalid BacKup header magic");
Uint32 ngId = base::readUInt32();
Uint32 ngId = base::readUint32();
ngId = ngId;
Uint32 numFiles = base::readUInt32();
Uint32 numFiles = base::readUint32();
/*int fileSize =*/ base::readUInt32();
/*int fileSize =*/ base::readUint32();
base::seek(8); // skip unknown data;
Uint32 totalSize = base::readUInt32();
Uint32 totalSize = base::readUint32();
base::seek(64); // Unknown (Most likely padding)
base::seek(8);
base::seek(6);
@@ -155,14 +152,14 @@ WiiBanner* WiiSaveReader::readBanner()
std::cerr << std::hex << (int)(md5Calc[i]);
std::cerr << std::endl;
base::setData(oldData, oldLen);
base::seek(oldPos, Stream::Beginning);
throw error::InvalidOperationException("WiiSaveReader::readBanner -> MD5 Mismatch");
base::seek(oldPos, SeekOrigin::Begin);
THROW_INVALID_DATA_EXCEPTION("MD5 Mismatch");
}
// Set the binary reader buffer;
base::setData(dec, 0xF0C0);
// Start reading the header
gameId = base::readUInt64();
bannerSize = base::readUInt32();
gameId = base::readUint64();
bannerSize = base::readUint32();
permissions = base::readByte();
/* unk =*/ base::readByte();
base::seek(0x10);
@@ -175,28 +172,28 @@ WiiBanner* WiiSaveReader::readBanner()
std::string gameTitle;
std::string subTitle;
magic = base::readUInt32();
magic = base::readUint32();
// Ensure that the header magic is valid.
if (magic != 0x5749424E)
{
// Make sure to reset m_reader values back to the old ones.
base::setData(oldData, oldLen);
base::seek(oldPos, Stream::Beginning);
throw error::InvalidOperationException("WiiSaveReader::readBanner -> Invalid Header Magic");
base::seek(oldPos, SeekOrigin::Begin);
THROW_INVALID_DATA_EXCEPTION("Invalid Header Magic");
}
flags = base::readUInt32();
animSpeed = base::readUInt16();
flags = base::readUint32();
animSpeed = base::readUint16();
base::seek(22);
gameTitle = base::readUnicode();
if (base::position() != 0x0080)
base::seek(0x0080, Stream::Beginning);
base::seek(0x0080, SeekOrigin::Begin);
subTitle = base::readUnicode();
if (base::position() != 0x00C0)
base::seek(0x00C0, Stream::Beginning);
base::seek(0x00C0, SeekOrigin::Begin);
WiiBanner* banner = new WiiBanner;
banner->setGameID(gameId);
@@ -231,7 +228,7 @@ WiiBanner* WiiSaveReader::readBanner()
}
base::setData(oldData, oldLen);
base::seek(oldPos, Stream::Beginning);
base::seek(oldPos, SeekOrigin::Begin);
return banner;
}
@@ -256,14 +253,14 @@ WiiFile* WiiSaveReader::readFile()
Uint8* filedata;
WiiFile* ret;
Uint32 magic = base::readUInt32();
Uint32 magic = base::readUint32();
if (magic != 0x03adf17e)
{
std::cerr << "Not a valid File entry header: 0x" << std::hex << magic << std::endl;
return NULL;
}
fileLen = base::readUInt32();
fileLen = base::readUint32();
permissions = base::readByte();
attributes = base::readByte();
type = (WiiFile::Type)base::readByte();
@@ -303,7 +300,7 @@ void WiiSaveReader::readCerts(Uint32 totalSize)
Uint8* sig = (Uint8*)base::readBytes(0x40);
Uint8* ngCert = (Uint8*)base::readBytes(0x180);
Uint8* apCert = (Uint8*)base::readBytes(0x180);
base::seek(0xF0C0, Stream::Beginning);
base::seek(0xF0C0, SeekOrigin::Begin);
Uint8* data = (Uint8*)base::readBytes(dataSize);
Uint8* hash;

View File

@@ -1,30 +1,33 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/WiiSaveWriter.hpp"
#include "Athena/WiiSave.hpp"
#include "Athena/WiiFile.hpp"
#include "Athena/WiiBanner.hpp"
#include "Athena/WiiImage.hpp"
#include "Athena/WiiSave.hpp"
#include "Athena/WiiFile.hpp"
#include "Athena/WiiBanner.hpp"
#include "Athena/BinaryWriter.hpp"
#include "Athena/Utility.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/InvalidDataException.hpp"
#include "WiiSaveWriter.hpp"
#include "WiiSave.hpp"
#include "WiiFile.hpp"
#include "WiiBanner.hpp"
#include "WiiImage.hpp"
#include "WiiSave.hpp"
#include "WiiFile.hpp"
#include "WiiBanner.hpp"
#include "BinaryWriter.hpp"
#include "aes.h"
#include "ec.h"
#include "utility.hpp"
#include "md5.h"
#include "sha1.h"
@@ -35,41 +38,37 @@
#include <iostream>
#include <iomanip>
namespace zelda
namespace Athena
{
namespace io
{
const Uint8 SD_KEY[16] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08, 0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d};
const Uint8 SD_IV[16] = {0x21, 0x67, 0x12, 0xe6, 0xaa, 0x1f, 0x68, 0x9f, 0x95, 0xc5, 0xa2, 0x23, 0x24, 0xdc, 0x6a, 0x98};
const Uint8 MD5_BLANKER[16] = {0x0e, 0x65, 0x37, 0x81, 0x99, 0xbe, 0x45, 0x17, 0xab, 0x06, 0xec, 0x22, 0x45, 0x1a, 0x57, 0x93};
WiiSaveWriter::WiiSaveWriter(const std::string &filename)
: base(filename)
{
base::setAutoResizing(true);
base::setEndianess(BigEndian);
base::setEndian(Endian::BigEndian);
}
bool WiiSaveWriter::writeSave(WiiSave *save, Uint8 *macAddress, Uint32 ngId, Uint8 *ngPriv, Uint8 *ngSig, Uint32 ngKeyId,const std::string &filepath)
{
if (!save)
THROW_INVALID_OPERATION_EXCEPTION("save cannot be NULL");
if (filepath != "")
m_filepath = filepath;
writeBanner(save->banner());
base::writeUInt32(0x70);
base::writeUInt32(0x426B0001);
base::writeUInt32(ngId); // NG-ID
base::writeUInt32(save->fileList().size());
base::writeUInt32(0); // Size of files;
base::writeUint32(0x70);
base::writeUint32(0x426B0001);
base::writeUint32(ngId); // NG-ID
base::writeUint32(save->fileList().size());
base::writeUint32(0); // Size of files;
base::seek(8);
base::writeUInt32(0); // totalSize
base::writeUint32(0); // totalSize
base::seek(64);
base::writeUInt64(save->banner()->gameID());
base::writeUint64(save->banner()->gameID());
base::writeBytes((Int8*)macAddress, 6);
base::seek(2); // unknown;
base::seek(0x10); // padding;
@@ -80,11 +79,11 @@ bool WiiSaveWriter::writeSave(WiiSave *save, Uint8 *macAddress, Uint32 ngId, Uin
}
int pos = base::position();
// Write size data
base::seek(0xF0C0 + 0x10, Stream::Beginning);
base::writeUInt32(totalSize);
base::seek(0xF0C0 + 0x1C, Stream::Beginning);
base::writeUInt32(totalSize + 0x3c0);
base::seek(pos, Stream::Beginning);
base::seek(0xF0C0 + 0x10, SeekOrigin::Begin);
base::writeUint32(totalSize);
base::seek(0xF0C0 + 0x1C, SeekOrigin::Begin);
base::writeUint32(totalSize + 0x3c0);
base::seek(pos, SeekOrigin::Begin);
writeCerts(totalSize, ngId, ngPriv, ngSig, ngKeyId);
@@ -95,8 +94,7 @@ bool WiiSaveWriter::writeSave(WiiSave *save, Uint8 *macAddress, Uint32 ngId, Uin
void WiiSaveWriter::writeBanner(WiiBanner *banner)
{
base::setEndianess(BigEndian);
base::setAutoResizing(true);
base::setEndian(Endian::BigEndian);
base::writeInt64(banner->gameID());
base::writeInt32((0x60a0+0x1200)*banner->icons().size());
base::writeByte((Int8)banner->permissions());
@@ -111,12 +109,12 @@ void WiiSaveWriter::writeBanner(WiiBanner *banner)
base::writeUnicode(banner->title());
if (base::position() != 0x0080)
base::seek(0x0080, Stream::Beginning);
base::seek(0x0080, SeekOrigin::Begin);
base::writeUnicode(banner->subtitle());
if (base::position() != 0x00C0)
base::seek(0x00C0, Stream::Beginning);
base::seek(0x00C0, SeekOrigin::Begin);
WiiImage* bannerImage = banner->bannerImage();
base::writeBytes((Int8*)bannerImage->data(), bannerImage->width()*bannerImage->height()*2);
@@ -140,7 +138,7 @@ void WiiSaveWriter::writeBanner(WiiBanner *banner)
Uint8* hash = new Uint8[0x10];
MD5Hash::MD5(hash, (Uint8*)base::data(), 0xF0C0);
base::seek(0x0E, Stream::Beginning);
base::seek(0x0E, SeekOrigin::Begin);
base::writeBytes((Int8*)hash, 0x10);
aes_set_key(SD_KEY);
@@ -150,9 +148,9 @@ void WiiSaveWriter::writeBanner(WiiBanner *banner)
memcpy(tmpIV, SD_IV, 16);
aes_encrypt(tmpIV, data, data, 0xF0C0);
base::seek(0, Stream::Beginning);
base::seek(0, SeekOrigin::Begin);
base::writeBytes((Int8*)data, 0xF0C0);
base::seek(0xF0C0, Stream::Beginning);
base::seek(0xF0C0, SeekOrigin::Begin);
}
Uint32 WiiSaveWriter::writeFile(WiiFile *file)
@@ -160,8 +158,8 @@ Uint32 WiiSaveWriter::writeFile(WiiFile *file)
Uint32 ret = 0x80;
// Write the File magic
base::writeUInt32(0x03ADF17E);
base::writeUInt32(file->length());
base::writeUint32(0x03ADF17E);
base::writeUint32(file->length());
base::writeByte(file->permissions());
base::writeByte(file->attributes());
base::writeByte(file->type());

View File

@@ -1,22 +1,22 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "ZQuestFile.hpp"
#include "Athena/ZQuestFile.hpp"
#include <string.h>
namespace zelda
namespace Athena
{
std::vector<std::string> GameStrings;
void initGameStrings()
@@ -53,7 +53,7 @@ const Uint32 ZQuestFile::Magic = 'Z' | ('Q' << 8) | ('S' << 16) | (('0' + ZQue
ZQuestFile::ZQuestFile()
: m_game(NoGame),
m_endian(LittleEndian),
m_endian(Endian::LittleEndian),
m_data(NULL),
m_length(0)
{

View File

@@ -1,29 +1,29 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "ZQuestFileReader.hpp"
#include "ZQuestFile.hpp"
#include "InvalidOperationException.hpp"
#include "Compression.hpp"
#include "InvalidDataException.hpp"
#include "Checksums.hpp"
#include "Athena/ZQuestFileReader.hpp"
#include "Athena/ZQuestFile.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/Compression.hpp"
#include "Athena/InvalidDataException.hpp"
#include "Athena/Checksums.hpp"
#include "Athena/Utility.hpp"
#include <iostream>
#include <iomanip>
#include <utility.hpp>
namespace zelda
namespace Athena
{
namespace io
{
@@ -47,18 +47,18 @@ ZQuestFile *ZQuestFileReader::read()
Uint32 checksum;
Uint8* data;
magic = base::readUInt32();
magic = base::readUint32();
if ((magic & 0x00FFFFFF) != (ZQuestFile::Magic & 0x00FFFFFF))
THROW_INVALID_DATA("Not a valid ZQuest file");
THROW_INVALID_DATA_EXCEPTION("Not a valid ZQuest file");
version = base::readUInt32();
version = base::readUint32();
if (version > ZQuestFile::Version)
THROW_INVALID_DATA("Unsupported ZQuest version");
THROW_INVALID_DATA_EXCEPTION("Unsupported ZQuest version");
compressedLen = base::readUInt32();
uncompressedLen = base::readUInt32();
compressedLen = base::readUint32();
uncompressedLen = base::readUint32();
if (version >= ZQUEST_VERSION_CHECK(2, 0, 0))
{
@@ -72,13 +72,13 @@ ZQuestFile *ZQuestFileReader::read()
}
}
BOM = base::readUInt16();
checksum = base::readUInt32();
BOM = base::readUint16();
checksum = base::readUint32();
}
else
{
game = (ZQuestFile::Game)base::readUInt32();
BOM = base::readUInt16();
game = (ZQuestFile::Game)base::readUint32();
BOM = base::readUint16();
std::cerr << "Test" << std::endl;
base::seek(0x0A);
}
@@ -87,15 +87,15 @@ ZQuestFile *ZQuestFileReader::read()
if (version >= ZQUEST_VERSION_CHECK(2, 0, 0))
{
if (checksum != zelda::Checksums::crc32(data, compressedLen))
if (checksum != Athena::Checksums::crc32(data, compressedLen))
{
delete[] data;
THROW_INVALID_DATA("Checksum mismatch, data corrupt");
THROW_INVALID_DATA_EXCEPTION("Checksum mismatch, data corrupt");
}
}
else
{
std::clog << "ZQuest version 0x" << std::uppercase << std::setw(8) << std::setfill('0') << std::hex << zelda::utility::swapU32(version);
std::clog << "ZQuest version 0x" << std::uppercase << std::setw(8) << std::setfill('0') << std::hex << Athena::utility::swapU32(version);
std::clog << " has no checksum field" << std::endl;
}
@@ -109,14 +109,14 @@ ZQuestFile *ZQuestFileReader::read()
delete[] dst;
delete[] data;
// TODO: Make proper exception
THROW_INVALID_DATA("Error decompressing data");
THROW_INVALID_DATA_EXCEPTION("Error decompressing data");
}
delete[] data;
data = dst;
}
return new ZQuestFile(game, BOM == 0xFEFF ? BigEndian : LittleEndian, data, uncompressedLen, gameString);
return new ZQuestFile(game, BOM == 0xFEFF ? Endian::BigEndian : Endian::LittleEndian, data, uncompressedLen, gameString);
}
} // io

View File

@@ -1,25 +1,25 @@
// This file is part of libZelda.
// This file is part of libAthena.
//
// libZelda is free software: you can redistribute it and/or modify
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// libAthena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "ZQuestFileWriter.hpp"
#include "InvalidOperationException.hpp"
#include "ZQuestFile.hpp"
#include "Compression.hpp"
#include "Checksums.hpp"
#include "Athena/ZQuestFileWriter.hpp"
#include "Athena/InvalidOperationException.hpp"
#include "Athena/ZQuestFile.hpp"
#include "Athena/Compression.hpp"
#include "Athena/Checksums.hpp"
namespace zelda
namespace Athena
{
namespace io
{
@@ -37,10 +37,10 @@ ZQuestFileWriter::ZQuestFileWriter(const std::string& filename)
void ZQuestFileWriter::write(ZQuestFile* quest, bool compress)
{
if (!quest)
THROW_INVALIDOPERATION_EXCEPTION("quest cannot be NULL");
THROW_INVALID_OPERATION_EXCEPTION("quest cannot be NULL");
base::writeUInt32(ZQuestFile::Magic);
base::writeUInt32(ZQuestFile::Version);
base::writeUint32(ZQuestFile::Magic);
base::writeUint32(ZQuestFile::Version);
Uint8* questData = quest->data();
Uint32 compLen;
if (compress)
@@ -56,25 +56,25 @@ void ZQuestFileWriter::write(ZQuestFile* quest, bool compress)
// Delete the compressed data since we won't be using it
delete[] compData;
compData = NULL;
base::writeUInt32(quest->length());
base::writeUint32(quest->length());
}
else
{
// Don't do delete on data
questData = compData;
base::writeUInt32(compLen);
base::writeUint32(compLen);
}
}
else
{
compLen = quest->length();
base::writeUInt32(quest->length());
base::writeUint32(quest->length());
}
base::writeUInt32(quest->length());
base::writeUint32(quest->length());
base::writeBytes((Int8*)quest->gameString().substr(0, 0x0A).c_str(), 0x0A);
base::writeUInt16(quest->endian() == BigEndian ? 0xFFFE : 0xFEFF);
base::writeUInt32(zelda::Checksums::crc32(questData, compLen));
base::writeUint16(quest->endian() == Endian::BigEndian ? 0xFFFE : 0xFEFF);
base::writeUint32(Athena::Checksums::crc32(questData, compLen));
base::writeUBytes(questData, compLen);
base::save();

View File

@@ -1,378 +0,0 @@
// This file is part of libZelda.
//
// libZelda is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "BinaryReader.hpp"
#include "IOException.hpp"
#include "FileNotFoundException.hpp"
#include "utility.hpp"
#include "utf8.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#ifdef HW_RVL
#include <malloc.h>
#endif // HW_RVL
namespace zelda
{
namespace io
{
BinaryReader::BinaryReader(const Stream& stream) :
Stream(stream)
{
Stream::setAutoResizing(false);
}
BinaryReader::BinaryReader(const Uint8* data, Uint64 length) :
Stream(data, length)
{
Stream::setAutoResizing(false);
}
BinaryReader::BinaryReader(const std::string& filename)
: m_filepath(filename)
{
Stream::setAutoResizing(false);
}
bool BinaryReader::readBit()
{
if (!m_data)
loadData();
return Stream::readBit();
}
Int8 BinaryReader::readByte()
{
if (!m_data)
loadData();
return Stream::readByte();
}
Uint8 BinaryReader::readUByte()
{
if (!m_data)
loadData();
return Stream::readUByte();
}
Int8* BinaryReader::readBytes(Int64 length)
{
if (!m_data)
loadData();
return Stream::readBytes(length);
}
Uint8* BinaryReader::readUBytes(Int64 length)
{
if (!m_data)
loadData();
return Stream::readUBytes(length);
}
void BinaryReader::writeByte(Int8)
{
throw error::IOException("BinaryReader::writeByte -> Stream not open for writing");
}
void BinaryReader::writeBytes(Int8*, Int64)
{
throw error::IOException("BinaryReader::writeBytes -> Stream not open for writing");
}
Int16 BinaryReader::readInt16()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int16) > m_length)
throw error::IOException("BinaryReader::readInt16 -> Position outside stream bounds");
Int16 ret = *(Int16*)(m_data + m_position);
m_position += sizeof(Int16);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swap16(ret);
return ret;
}
Uint16 BinaryReader::readUInt16()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint16) > m_length)
throw error::IOException("BinaryReader::readUint16 -> Position outside stream bounds");
Uint16 ret = *(Uint16*)(m_data + m_position);
m_position += sizeof(Uint16);
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swapU16(ret);
return ret;
}
Int32 BinaryReader::readInt32()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int32) > m_length)
throw error::IOException("BinaryReader::readUint32 -> Position outside stream bounds");
Int32 ret = *(Int32*)(m_data + m_position);
m_position += 4;
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swap32(ret);
return ret;
}
Uint32 BinaryReader::readUInt32()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint32) > m_length)
throw error::IOException("BinaryReader::readUint32 -> Position outside stream bounds");
Uint32 ret = *(Uint32*)(m_data + m_position);
m_position += 4;
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swapU32(ret);
return ret;
}
Int64 BinaryReader::readInt64()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int64) > m_length)
throw error::IOException("BinaryReader::readInt64 -> Position outside stream bounds");
Int64 ret = *(Int64*)(m_data + m_position);
m_position += 8;
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swap64(ret);
return ret;
}
Uint64 BinaryReader::readUInt64()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint64) > m_length)
throw error::IOException("BinaryReader::readUInt64 -> Position outside stream bounds");
Uint64 ret = *(Uint64*)(m_data + m_position);
m_position += 8;
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swapU64(ret);
return ret;
}
float BinaryReader::readFloat()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(float) > m_length)
throw error::IOException("BinaryReader::readFloat -> Position outside stream bounds");
float ret = *(float*)(m_data + m_position);
m_position += 4;
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swapFloat(ret);
return ret;
}
double BinaryReader::readDouble()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(double) > m_length)
throw error::IOException("BinaryReader::readDouble -> Position outside stream bounds");
double ret = *(double*)(m_data + m_position);
m_position += 8;
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
ret = utility::swapDouble(ret);
return ret;
}
bool BinaryReader::readBool()
{
if (!m_data)
loadData();
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(bool) > m_length)
throw error::IOException("BinaryReader::readBool -> Position outside stream bounds");
bool ret = *(bool*)(m_data + m_position);
m_position += 1;
return ret;
}
std::string BinaryReader::readUnicode()
{
if (!m_data)
loadData();
std::string ret;
std::vector<short> tmp;
for(;;)
{
short chr = readUInt16();
if (chr)
tmp.push_back(chr);
else
break;
};
utf8::utf16to8(tmp.begin(), tmp.end(), back_inserter(ret));
return ret;
}
std::string BinaryReader::readString()
{
std::string ret = "";
Uint8 chr = readByte();
while (chr != 0)
{
ret += chr;
chr = readByte();
}
return ret;
}
void BinaryReader::setProgressCallback(std::function<void (int)> cb)
{
m_progressCallback = cb;
}
void BinaryReader::loadData()
{
FILE* in;
Uint32 length;
in = fopen(m_filepath.c_str(), "rb");
if (!in)
throw error::FileNotFoundException(m_filepath);
fseek(in, 0, SEEK_END);
length = ftell(in);
fseek(in, 0, SEEK_SET);
#ifdef HW_RVL
m_data = (Uint8*)memalign(32, length);
#else
m_data = new Uint8[length];
#endif
Uint32 done = 0;
Uint32 blocksize = BLOCKSZ;
do
{
if (blocksize > length - done)
blocksize = length - done;
Int32 ret = fread(m_data + done, 1, blocksize, in);
if (ret < 0)
throw error::IOException("BinaryReader::BinaryReader -> reading data from disk");
else if (ret == 0)
break;
done += ret;
if (m_progressCallback)
m_progressCallback((int)((float)(done* 100.f)/length));
} while (done < length);
fclose(in);
m_length = length;
m_position = 0;
m_bitPosition = 0;
}
bool BinaryReader::isOpenForWriting()
{
return false;
}
}
}

View File

@@ -1,324 +0,0 @@
// This file is part of libZelda.
//
// libZelda is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "BinaryWriter.hpp"
#include "IOException.hpp"
#include "InvalidOperationException.hpp"
#include "FileNotFoundException.hpp"
#include "utility.hpp"
#include "utf8.h"
#include <stdio.h>
#include <string.h>
#include <vector>
#include <iostream>
#ifdef HW_RVL
#include <malloc.h>
#endif // HW_RVL
namespace zelda
{
namespace io
{
BinaryWriter::BinaryWriter(const Uint8* data, Uint64 length)
: Stream(data, length)
{}
BinaryWriter::BinaryWriter(const Stream& stream) :
Stream(stream)
{}
BinaryWriter::BinaryWriter(const std::string& filename)
: m_filepath(filename)
{
m_length = 0x10;
m_bitPosition = 0;
m_position = 0;
#ifdef HW_RVL
m_data = (Uint8*)memalign(32, m_length);
#else
m_data = new Uint8[m_length];
#endif
if (!m_data)
throw error::IOException("BinaryWriter::BinaryWriter -> Could not allocate memory!");
memset(m_data, 0, m_length);
}
void BinaryWriter::setFilepath(const std::string& filepath)
{
m_filepath = filepath;
}
std::string BinaryWriter::filepath() const
{
return m_filepath;
}
void BinaryWriter::save(const std::string& filename)
{
if (filename.empty() && m_filepath.empty())
throw error::InvalidOperationException("BinaryWriter::save -> No file specified, cannot save.");
if (!filename.empty())
m_filepath = filename;
FILE* out = fopen(m_filepath.c_str(), "wb");
if (!out)
throw error::FileNotFoundException(m_filepath);
Uint32 done = 0;
Uint32 blocksize = BLOCKSZ;
do
{
if (blocksize > m_length - done)
blocksize = m_length - done;
Int32 ret = fwrite(m_data + done, 1, blocksize, out);
if (ret < 0)
throw error::IOException("BinaryWriter::save Error writing data to disk");
else if (ret == 0)
break;
done += blocksize;
}while (done < m_length);
fclose(out);
}
Int8 BinaryWriter::readByte()
{
throw error::IOException("BinaryWriter::readByte -> Stream not open for reading");
}
Int8* BinaryWriter::readBytes(Int64)
{
throw error::IOException("BinaryWriter::readBytes -> Stream not open for reading");
}
void BinaryWriter::writeInt16(Int16 val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int16) > m_length && m_autoResize)
resize(m_position + sizeof(Int16));
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteInt16 -> Position outside stream bounds");
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swap16(val);
*(Int16*)(m_data + m_position) = val;
m_position += sizeof(Int16);
}
void BinaryWriter::writeUInt16(Uint16 val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint16) > m_length && m_autoResize)
resize(m_position + sizeof(Uint16));
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteUInt16 -> Position outside stream bounds");
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swapU16(val);
*(Uint16*)(m_data + m_position) = val;
m_position += sizeof(Uint16);
}
void BinaryWriter::writeInt32(Int32 val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int32) > m_length && m_autoResize)
resize(m_position + sizeof(Int32));
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteInt32 -> Position outside stream bounds");
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swap32(val);
*(Int32*)(m_data + m_position) = val;
m_position += sizeof(Int32);
}
void BinaryWriter::writeUInt32(Uint32 val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint32) > m_length && m_autoResize)
resize(m_position + sizeof(Uint32));
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteUInt32 -> Position outside stream bounds");
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swapU32(val);
*(Uint32*)(m_data + m_position) = val;
m_position += sizeof(Uint32);
}
void BinaryWriter::writeInt64(Int64 val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int64) > m_length && m_autoResize)
resize(m_position + sizeof(Int64));
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteInt64 -> Position outside stream bounds");
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swap64(val);
*(Int64*)(m_data + m_position) = val;
m_position += sizeof(Int64);
}
void BinaryWriter::writeUInt64(Uint64 val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint64) > m_length && m_autoResize)
resize(m_position + sizeof(Uint64));
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteUInt64 -> Position outside stream bounds");
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swapU64(val);
*(Uint64*)(m_data + m_position) = val;
m_position += sizeof(Uint64);
}
void BinaryWriter::writeFloat(float val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(float) > m_length && m_autoResize)
resize(m_position + sizeof(float));
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteFloat -> Position outside stream bounds");
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swapFloat(val);
*(float*)(m_data + m_position) = val;
m_position += sizeof(float);
}
void BinaryWriter::writeDouble(double val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(double) > m_length && m_autoResize)
resize(m_position + sizeof(double));
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteDouble -> Position outside stream bounds");
if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian))
val = utility::swapDouble(val);
*(double*)(m_data + m_position)= val;
m_position += sizeof(double);
}
void BinaryWriter::writeBool(bool val)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(bool) > m_length && m_autoResize)
resize(m_position + sizeof(bool));
else if (m_position > m_length)
throw error::IOException("BinaryWriter::WriteBool -> Position outside stream bounds");
*(bool*)(m_data + m_position) = val;
m_position += sizeof(bool);
}
void BinaryWriter::writeUnicode(const std::string& str)
{
std::string tmpStr = "\xEF\xBB\xBF" + str;
std::vector<short> tmp;
utf8::utf8to16(tmpStr.begin(), tmpStr.end(), back_inserter(tmp));
for (Uint16 chr : tmp)
{
if (chr != 0xFEFF)
writeInt16(chr);
}
}
void BinaryWriter::writeString(const std::string& str)
{
for (Uint8 c : str)
{
if (c != '\0')
writeUByte(c);
}
writeUByte(0);
}
bool BinaryWriter::isOpenForReading()
{
return false;
}
} // io
} // zelda

View File

@@ -1,57 +0,0 @@
#include "SkywardSwordFile.hpp"
#include "SkywardSwordQuest.hpp"
#include "InvalidOperationException.hpp"
namespace zelda
{
SkywardSwordFile::SkywardSwordFile()
: m_numQuests(0)
{
}
SkywardSwordFile::SkywardSwordFile(std::vector<SkywardSwordQuest*> quests)
: m_numQuests(0)
{
m_quests = quests;
}
SkywardSwordFile::~SkywardSwordFile()
{
}
void SkywardSwordFile::addQuest(zelda::SkywardSwordQuest *q)
{
// Do not allow more than 3 quests
if (m_quests.size() >= 3)
return;
m_quests.push_back(q);
}
SkywardSwordQuest *SkywardSwordFile::quest(Uint32 id)
{
if (id > m_quests.size() - 1)
throw zelda::error::InvalidOperationException("SSFile::quest -> id cannot be "
"greater than the number of quests");
return m_quests[id];
}
std::vector<SkywardSwordQuest*> SkywardSwordFile::questList() const
{
return m_quests;
}
void SkywardSwordFile::setRegion(Region region)
{
m_region = region;
}
Region SkywardSwordFile::region() const
{
return m_region;
}
} // zelda

View File

@@ -1,68 +0,0 @@
#include "SkywardSwordFileReader.hpp"
#include "SkywardSwordFile.hpp"
#include "SkywardSwordQuest.hpp"
#include "InvalidOperationException.hpp"
#include <iostream>
namespace zelda
{
namespace io
{
SkywardSwordFileReader::SkywardSwordFileReader(Uint8* data, Uint64 length)
: base(data, length)
{
base::setEndianess(BigEndian);
}
SkywardSwordFileReader::SkywardSwordFileReader(const std::string& filename)
: base(filename)
{
base::setEndianess(BigEndian);
}
SkywardSwordFile* SkywardSwordFileReader::read()
{
SkywardSwordFile* file = NULL;
try
{
if (base::length() != 0xFBE0)
throw zelda::error::InvalidOperationException("SSFileReader::read -> File not the expected size of 0xFBE0");
Uint32 magic = base::readUInt32();
if (magic != SkywardSwordFile::USMagic && magic != SkywardSwordFile::JAMagic && magic != SkywardSwordFile::EUMagic)
throw zelda::error::InvalidOperationException("SSFileReader::read -> Not a valid Skyward Sword save file");
base::seek(0x01C, base::Beginning);
Uint32 headerSize = base::readUInt32(); // Seems to be (headerSize - 1)
if (headerSize != 0x1D)
throw zelda::error::InvalidOperationException("SSFileHeader::read -> Invalid header size, Corrupted data?");
// Time to read in each slot
file = new SkywardSwordFile;
file->setRegion((magic == SkywardSwordFile::USMagic ? NTSCURegion : (magic == SkywardSwordFile::JAMagic ? NTSCJRegion : PALRegion)));
for (int i = 0; i < 3; i++)
{
SkywardSwordQuest* q = new SkywardSwordQuest((Uint8*)base::readBytes(0x53C0), 0x53C0);
Uint64 pos = base::position();
// seek to the skip data for this particular quest
base::seek(0xFB60 + (i * 0x24), base::Beginning);
q->setSkipData(base::readUBytes(0x24));
base::seek(pos, base::Beginning);
file->addQuest(q);
}
}
catch(...)
{
delete file;
file = NULL;
throw;
}
return file;
}
} // io
} // zelda

View File

@@ -1,51 +0,0 @@
#include "SkywardSwordFileWriter.hpp"
#include "SkywardSwordFile.hpp"
#include "SkywardSwordQuest.hpp"
namespace zelda
{
namespace io
{
SkywardSwordFileWriter::SkywardSwordFileWriter(Uint8 *data, Uint64 len)
: base(data, len)
{
base::setEndianess(BigEndian);
}
SkywardSwordFileWriter::SkywardSwordFileWriter(const std::string &filename)
: base(filename)
{
base::setEndianess(BigEndian);
}
void SkywardSwordFileWriter::write(SkywardSwordFile *file)
{
Uint32 magic = (file->region() == NTSCURegion ? SkywardSwordFile::USMagic :
(file->region() == NTSCJRegion ? SkywardSwordFile::JAMagic : SkywardSwordFile::EUMagic));
base::writeUInt32(magic);
base::seek(0x1C, base::Beginning);
base::writeUInt32(0x1D);
std::vector<SkywardSwordQuest*> quests = file->questList();
int i = 0;
for (SkywardSwordQuest* q : quests)
{
// Write the save data
base::writeUBytes(q->data(), q->length());
Uint64 pos = base::position();
// Write the slots skip data
base::seek(0xFB60 + (i * 0x24), base::Beginning);
base::writeUBytes(q->skipData(), q->skipLength());
base::seek(pos, base::Beginning);
i++;
}
// write those padding bytes
base::seek(0xFBE0, base::Beginning);
save();
}
} // io
} // zelda

View File

@@ -1,34 +0,0 @@
#include "SkywardSwordQuest.hpp"
namespace zelda
{
SkywardSwordQuest::SkywardSwordQuest(Uint8 *data, Uint32 len)
: ZQuestFile(ZQuestFile::SS, BigEndian, data, len),
m_skipData(NULL),
m_skipLength(0)
{
}
void SkywardSwordQuest::setSkipData(const Uint8 *data, Uint32 len)
{
if (m_skipData)
{
delete[] m_skipData;
m_skipData = NULL;
}
m_skipData = (Uint8*)data;
m_skipLength = len;
}
Uint8 *SkywardSwordQuest::skipData() const
{
return m_skipData;
}
Uint32 SkywardSwordQuest::skipLength() const
{
return m_skipLength;
}
} // zelda

View File

@@ -1,383 +0,0 @@
// This file is part of libZelda.
//
// libZelda is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "Stream.hpp"
#include "IOException.hpp"
#include "InvalidOperationException.hpp"
#include <string.h>
#include <sstream>
#ifdef HW_RVL
#include <malloc.h>
#endif // HW_RVL
namespace zelda
{
namespace io
{
const Uint32 Stream::BLOCKSZ = (32*1024);
Stream::Stream() :
m_bitPosition(0),
m_position(0),
m_length(0),
m_endian(LittleEndian),
m_data(NULL),
m_autoResize(true)
{}
Stream::Stream(const Uint8* data, Uint64 length) :
m_bitPosition(0),
m_position(0),
m_endian(LittleEndian),
m_autoResize(true)
{
if (length <= 0)
throw error::InvalidOperationException("Stream::Stream -> Length cannot be <= to 0");
m_length = length;
if (data)
m_data = (Uint8*)data;
else
{
#ifdef HW_RVL
m_data = (Uint8*)memalign(32, m_length);
#else
m_data = new Uint8[m_length];
#endif
memset(m_data, 0, m_length);
}
}
Stream::Stream(Int64 length) :
m_bitPosition(0),
m_position(0),
m_length(length)
{
#ifdef HW_RVL
m_data = (Uint8*)memalign(32, m_length);
#else
m_data = new Uint8[m_length];
#endif
memset(m_data, 0, m_length);
}
Stream::Stream(Stream* stream)
{
if (m_data)
delete[] m_data;
m_data = NULL;
m_data = stream->m_data;
m_position = stream->m_position;
m_length = stream->m_length;
}
Stream::~Stream()
{
if (m_data)
#ifdef HW_RVL
free(m_data);
#else
delete[] m_data;
#endif
m_data = NULL;
m_position = 0;
m_length = 0;
m_endian = LittleEndian;
m_autoResize = false;
}
void Stream::writeBit(bool val)
{
if (m_position + sizeof(Uint8) > m_length && m_autoResize)
resize(m_position + sizeof(Uint8));
else if (m_position > m_length)
throw error::IOException("Stream::writeBit() -> Position outside stream bounds");
if (val)
*(Uint8*)(m_data + m_position) |= (1 << m_bitPosition);
else
*(Uint8*)(m_data + m_position) &= ~(1 << m_bitPosition);
m_bitPosition++;
if (m_bitPosition > 7)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
}
void Stream::writeUByte(Uint8 byte)
{
writeByte((Int8)byte);
}
void Stream::writeByte(Int8 byte)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + 1 > m_length && m_autoResize)
resize(m_position + 1);
else if (m_position > m_length)
throw error::IOException("Stream::writeByte() -> Position outside stream bounds");
*(Int8*)(m_data + m_position) = byte;
m_position++;
}
void Stream::writeUBytes(Uint8* data, Int64 length)
{
writeBytes((Int8*)data, length);
}
void Stream::writeBytes(Int8* data, Int64 length)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (!data)
throw error::InvalidOperationException("Stream::writeBytes -> data cannnot be NULL");
if (m_position + length > m_length && m_autoResize)
resize(m_position + length);
else if (m_position > m_length)
throw error::IOException("Stream::writeBytes -> Position outside stream bounds");
memcpy((Int8*)(m_data + m_position), data, length);
m_position += length;
}
bool Stream::readBit()
{
if (m_position + sizeof(Uint8) > m_length && m_autoResize)
resize(m_position + sizeof(Uint8));
else if (m_position > m_length)
throw error::IOException("Stream::writeInt16 -> Position outside stream bounds");
bool ret = (*(Uint8*)(m_data + m_position) & (1 << m_bitPosition));
m_bitPosition++;
if (m_bitPosition > 7)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
return ret;
}
Int8 Stream::readByte()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + 1 > m_length)
throw error::IOException("Stream::readByte -> Position passed stream bounds");
return *(Int8*)(m_data + m_position++);
}
Uint8 Stream::readUByte()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + 1 > m_length)
throw error::IOException("Stream::readUByte -> Position passed stream bounds");
return *(Uint8*)(m_data + m_position++);
}
Uint8 *Stream::readUBytes(Int64 length)
{
return (Uint8*)readBytes(length);
}
Int8* Stream::readBytes(Int64 length)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + length > m_length)
throw error::IOException("Stream::readBytes -> Position passed stream bounds: " + m_position);
Int8* ret;
#ifdef HW_RVL
ret = (Int8*)memalign(32, length);
#else
ret = new Int8[length];
#endif
memcpy(ret, (const Int8*)(m_data + m_position), length);
m_position += length;
return ret;
}
void Stream::seek(Int64 position, SeekOrigin origin)
{
switch (origin)
{
case Beginning:
if ((position < 0 || (Int64)position > (Int64)m_length) && !m_autoResize)
{
std::stringstream ss;
ss << position;
throw error::IOException("Stream::seek() Beginnning -> Position outside stream bounds: " + ss.str());
}
if ((Uint64)position > m_length)
this->resize(position);
m_position = position;
break;
case Current:
if ((((Int64)m_position + position) < 0 || (m_position + position) > m_length) && !m_autoResize)
{
std::stringstream ss;
ss << (m_position + position);
throw error::IOException("Stream::seek() Current -> Position outside stream bounds: " + ss.str());
}
else if ((m_position + position) > m_length)
this->resize(m_position + position);
m_position += position;
break;
case End:
if ((((Int64)m_length - position < 0) || (m_length - position) > m_length) && !m_autoResize)
{
std::stringstream ss;
ss << std::hex << "0x" << (m_length - position);
throw error::IOException("Stream::seek() End -> Position outside stream bounds " + ss.str());
}
else if ((m_length - position) > m_length)
this->resize(m_length - position);
m_position = m_length - position;
break;
}
}
void Stream::resize(Uint64 newSize)
{
if (newSize < m_length)
throw error::InvalidOperationException("Stream::resize() -> New size cannot be less to the old size.");
// Allocate and copy new buffer
#ifdef HW_RVL
Uint8* newArray = (Uint8*)memalign(32, newSize);
#else
Uint8* newArray = new Uint8[newSize];
#endif
memset(newArray, 0, newSize);
memcpy(newArray, m_data, m_length);
// Delete the old one
#ifdef HW_RVL
free(m_data);
#else
delete[] m_data;
#endif
// Swap the pointer and size out for the new ones.
m_data = newArray;
m_length = newSize;
}
void Stream::setData(const Uint8* data, Uint64 length)
{
if (m_data)
#ifdef HW_RVL
free(m_data);
#else
delete[] m_data;
#endif
m_data = (Uint8*)data;
m_length = length;
m_position = 0;
}
Uint8* Stream::data() const
{
Uint8* ret = new Uint8[m_length];
memset(ret, 0, m_length);
memcpy(ret, m_data, m_length);
return ret;
}
Int64 Stream::length() const
{
return m_length;
}
Int64 Stream::position() const
{
return m_position;
}
bool Stream::atEnd() const
{
return m_position >= m_length;
}
void Stream::setAutoResizing(bool val)
{
m_autoResize = val;
}
bool Stream::autoResizing() const
{
return m_autoResize;
}
bool Stream::isOpenForReading() const
{
return true;
}
bool Stream::isOpenForWriting() const
{
return true;
}
void Stream::setEndianess(Endian endian)
{
m_endian = endian;
}
Endian Stream::endian() const
{
return m_endian;
}
} // io
} // zelda

View File

@@ -1,288 +0,0 @@
// This file is part of libZelda.
//
// libZelda is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libZelda is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "TextStream.hpp"
#include <stdio.h>
#include "FileNotFoundException.hpp"
#include "InvalidOperationException.hpp"
#include "IOException.hpp"
namespace zelda
{
namespace io
{
TextStream::TextStream(const std::string& filename, Uint32 fileMode, AccessMode accessMode) :
m_filename(filename),
m_textmode(fileMode),
m_accessmode(accessMode),
m_currentLine(0)
{
setAutoResizing(true);
FILE* in;
int length;
in = fopen(filename.c_str(), "rb");
if (!in)
{
if((fileMode & Create) != Create)
throw error::FileNotFoundException(filename.c_str());
in = fopen(filename.c_str(), "w+b");
}
if ((fileMode & Truncate) != Truncate)
{
fseek(in, 0, SEEK_END);
length = ftell(in);
fseek(in, 0, SEEK_SET);
m_data = new Uint8[length];
fread(m_data, 1, length, in);
fclose(in);
}
else
{
length = 1;
m_data = new Uint8[1];
}
if ((fileMode & Append) == Append)
m_position = length;
else
m_position = 0;
m_length = length;
m_startLength = length;
loadLines();
}
TextStream::TextStream()
: Stream()
{}
void TextStream::save(const std::string& filename)
{
if (m_accessmode != WriteOnly && m_accessmode != ReadWrite)
throw error::InvalidOperationException("TextStream::save -> Stream not open for writing");
if (filename != std::string())
m_filename = filename;
// We need a new buffer to write the new lines
if (m_data)
{
delete[] m_data;
m_data = NULL;
}
m_position = 0;
m_length = 1;
// Set the new buffer
m_data = new Uint8[m_length];
// Now write all the strings to the new buffer
for (std::string s : m_lines)
writeBytes((Int8*)s.c_str(), s.size());
writeByte('\n');
FILE* out = fopen(m_filename.c_str(), "wb");
if(out)
{
fwrite(m_data, 1, m_length, out);
fclose(out);
}
else
throw error::FileNotFoundException(m_filename);
}
std::string TextStream::readLine()
{
if (m_accessmode != ReadOnly && m_accessmode != ReadWrite)
throw error::InvalidOperationException("TextStream::readLine -> Stream not open for reading");
if (m_currentLine > m_lines.size())
throw error::IOException("TextStream::readLine -> Position past stream bounds");
return m_lines[m_currentLine++];
}
void TextStream::writeLine(const std::string& str)
{
if (m_accessmode != WriteOnly && m_accessmode != ReadWrite)
throw error::InvalidOperationException("TextStream::writeLine -> Stream not open for writing");
else if (m_currentLine >= m_lines.size())
{
m_lines.push_back(str + "\n");
m_currentLine++;
return;
}
m_lines[m_currentLine++] = str + "\n";
}
void TextStream::writeLines(std::vector<std::string> strings)
{
if (m_accessmode != WriteOnly && m_accessmode != ReadWrite)
throw error::InvalidOperationException("TextStream::writeLines -> Stream not open for writing");
for (std::string s: strings)
writeLine(s);
}
std::vector<std::string> TextStream::readLines(Uint32 numLines)
{
if (m_accessmode != ReadOnly && m_accessmode != ReadWrite)
throw error::InvalidOperationException("TextStream::readLines -> Stream not open for reading");
if (numLines > m_lines.size())
throw error::InvalidOperationException("TextStream::readLines -> numLines exceeds the number of stored strings.");
Uint32 currentLine = m_currentLine;
std::vector<std::string> ret;
while ((m_currentLine++) <= currentLine + numLines)
ret.push_back(m_lines[m_currentLine]);
return ret;
}
std::string TextStream::readLineAt(Uint32 line)
{
if (m_accessmode != ReadOnly && m_accessmode != ReadWrite)
throw error::InvalidOperationException("TextStream::readLineAt -> Stream not open for reading");
if (line <= 0)
throw error::InvalidOperationException("TextStream::readLineAt -> A line cannot be zero indexed");
if ((line - 1) >= m_lines.size())
throw error::IOException("TextStream::readLineAt -> Line index out of range");
return m_lines[line - 1];
}
void TextStream::writeLineAt(Uint32 line, const std::string& str)
{
if (m_accessmode != WriteOnly && m_accessmode != ReadWrite)
throw error::InvalidOperationException("TextStream::writeLineAt -> Stream not open for reading");
if (line <= 0)
throw error::InvalidOperationException("TextStream::writeLineAt -> A line cannot be zero indexed");
m_currentLine = line;
writeLine(str);
}
std::vector<std::string> TextStream::readAllLines()
{
if (m_accessmode != ReadOnly && m_accessmode != ReadWrite)
throw error::InvalidOperationException("TextWriter::readAllLines -> Stream not open for reading");
return m_lines;
}
void TextStream::setCurrentLine(Uint32 line)
{
if (line <= 0)
throw error::InvalidOperationException("TextWriter::setCurrentLine -> A line cannot be zero indexed");
m_currentLine = line - 1;
}
Uint32 TextStream::currentLine() const
{
return m_currentLine + 1;
}
void TextStream::setAccessMode(AccessMode mode)
{
m_accessmode = mode;
}
TextStream::AccessMode TextStream::accessMode() const
{
return m_accessmode;
}
void TextStream::setTextMode(TextMode mode)
{
m_textmode = mode;
}
Uint32 TextStream::textMode() const
{
return m_textmode;
}
void TextStream::truncate()
{
m_lines.clear();
}
bool TextStream::isOpenForReading() const
{
return ((m_accessmode == ReadOnly || m_accessmode == ReadWrite) && m_accessmode != WriteOnly);
}
bool TextStream::isOpenForWriting() const
{
return ((m_accessmode == WriteOnly || m_accessmode == ReadWrite) && m_accessmode != ReadOnly);
}
// PRIVATE FUNCTIONS
void TextStream::loadLines()
{
try
{
while (!atEnd())
{
std::string line;
Uint8 c;
for (;;)
{
c = readByte();
if (c == '\r' || c == '\n')
{
m_currentLine++;
line.push_back(c);
if (*(Uint8*)(m_data + m_position + 1) == '\n')
{
line.push_back('\n');
m_position++; // advance position past the new line character
}
break;
}
if (c == '\0')
{
line.push_back('\n');
break;
}
line.push_back(c);
}
m_lines.push_back(line);
}
}
catch(...)
{
// The stream MAY throw an out of range error but we're not concerned with it
}
}
} // io
} // zelda

View File

@@ -8,7 +8,7 @@
// Not all of these headers are necessary, figure out which ones are actually used and prune those that are irrelevant.
#include <string.h>
#include <utility.hpp>
#include "Athena/Utility.hpp"
#include "bn.h"
#include "ec.h"
@@ -330,7 +330,7 @@ void generate_ecdsa(Uint8 *R, Uint8 *S, Uint8 *k, Uint8 *hash)
elt_zero(e);
memcpy(e + 10, hash, 20);
zelda::utility::fillRandom(m, sizeof(m));
Athena::utility::fillRandom(m, sizeof(m));
m[0] = 0;
// R = (mG).x
@@ -405,11 +405,11 @@ bool check_ec(Uint8 *ng, Uint8 *ap, Uint8 *sig, Uint8 *sig_hash)
void make_ec_cert(Uint8 *cert, Uint8 *sig, char *signer, char *name, Uint8 *priv, Uint32 key_id )
{
memset(cert, 0, 0x180);
*(Uint32*)(cert) = zelda::utility::swapU32(0x10002);
*(Uint32*)(cert) = Athena::utility::swapU32(0x10002);
memcpy((char*)cert + 4, sig, 60);
strcpy((char*)cert + 0x80, signer);
*(Uint32*)(cert + 0xc0) = zelda::utility::swapU32(2);
*(Uint32*)(cert + 0xc0) = Athena::utility::swapU32(2);
strcpy((char*)cert + 0xc4, name);
*(Uint32*)(cert + 0x104) = zelda::utility::swapU32(key_id);
*(Uint32*)(cert + 0x104) = Athena::utility::swapU32(key_id);
ec_priv_to_pub(priv, cert + 0x108);
}

View File

@@ -40,7 +40,7 @@
#include "sha1.h"
#include <string.h>
#include <utility.hpp>
#include "Athena/Utility.hpp"
/*
* Define the circular shift macro
@@ -386,8 +386,8 @@ Uint8* getSha1( Uint8 * stuff, Uint32 stuff_size )
for( int i = 0; i < 5 ; i++ )
{
int val = sha.Message_Digest[ i ];
if (!zelda::utility::isSystemBigEndian())
val = zelda::utility::swap32(val);
if (!Athena::utility::isSystemBigEndian())
val = Athena::utility::swap32(val);
memcpy( (char*)ret + ( i * 4 ), &val, 4 );
}