mirror of
https://github.com/libAthena/athena.git
synced 2025-12-09 21:47:52 +00:00
* Major rewrite
This commit is contained in:
@@ -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];
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
506
src/Athena/BinaryReader.cpp
Normal 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
505
src/Athena/BinaryWriter.cpp
Normal 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
|
||||
@@ -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
|
||||
{
|
||||
@@ -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
333
src/Athena/FileReader.cpp
Normal 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
298
src/Athena/FileWriter.cpp
Normal 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
48
src/Athena/Global.cpp
Normal 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;
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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
|
||||
{
|
||||
71
src/Athena/SkywardSwordFile.cpp
Normal file
71
src/Athena/SkywardSwordFile.cpp
Normal 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
|
||||
84
src/Athena/SkywardSwordFileReader.cpp
Normal file
84
src/Athena/SkywardSwordFileReader.cpp
Normal 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
|
||||
75
src/Athena/SkywardSwordFileWriter.cpp
Normal file
75
src/Athena/SkywardSwordFileWriter.cpp
Normal 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
|
||||
49
src/Athena/SkywardSwordQuest.cpp
Normal file
49
src/Athena/SkywardSwordQuest.cpp
Normal 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
|
||||
@@ -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
|
||||
{
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
@@ -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());
|
||||
@@ -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
|
||||
{
|
||||
@@ -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
|
||||
{
|
||||
@@ -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
|
||||
@@ -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() :
|
||||
@@ -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?
|
||||
@@ -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) :
|
||||
@@ -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()
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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
|
||||
@@ -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();
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
383
src/Stream.cpp
383
src/Stream.cpp
@@ -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
|
||||
@@ -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
|
||||
|
||||
10
src/ec.cpp
10
src/ec.cpp
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user