mirror of https://github.com/libAthena/athena.git
* Added SkywardSword classes
* Added missing readUBytes function in zelda::io::Stream
This commit is contained in:
parent
162d2753dc
commit
baf16a6fbd
|
@ -177,6 +177,7 @@ protected:
|
||||||
#define BINARYREADER_BASE \
|
#define BINARYREADER_BASE \
|
||||||
private: \
|
private: \
|
||||||
typedef zelda::io::BinaryReader base;
|
typedef zelda::io::BinaryReader base;
|
||||||
|
|
||||||
#endif // BINARYREADER_BASE
|
#endif // BINARYREADER_BASE
|
||||||
|
|
||||||
#endif // __BINARYREADER_HPP__
|
#endif // __BINARYREADER_HPP__
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef __SSFILE_HPP__
|
||||||
|
#define __SSFILE_HPP__
|
||||||
|
|
||||||
|
#include "Types.hpp"
|
||||||
|
|
||||||
|
// standard lib
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace zelda
|
||||||
|
{
|
||||||
|
class SSQuest;
|
||||||
|
|
||||||
|
class SSFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum MagicNumbers
|
||||||
|
{
|
||||||
|
USMagic = 0x534F5545,
|
||||||
|
JAMagic = 0x534F554A,
|
||||||
|
EUMagic = 0x534F5550
|
||||||
|
};
|
||||||
|
|
||||||
|
SSFile();
|
||||||
|
SSFile(std::vector<SSQuest*> quests);
|
||||||
|
~SSFile();
|
||||||
|
|
||||||
|
void addQuest(SSQuest* q);
|
||||||
|
SSQuest* quest(Uint32 id);
|
||||||
|
std::vector<SSQuest*> questList() const;
|
||||||
|
|
||||||
|
void setRegion(Region region);
|
||||||
|
Region region() const;
|
||||||
|
private:
|
||||||
|
Region m_region;
|
||||||
|
// A vector is a bit overkill
|
||||||
|
std::vector<SSQuest*> m_quests;
|
||||||
|
Uint32 m_numQuests;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // __SSFILE_HPP__
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef __SSFILEREADER_HPP__
|
||||||
|
#define __SSFILEREADER_HPP__
|
||||||
|
|
||||||
|
#include "BinaryReader.hpp"
|
||||||
|
|
||||||
|
namespace zelda
|
||||||
|
{
|
||||||
|
class SSFile;
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
class SSFileReader : public BinaryReader
|
||||||
|
{
|
||||||
|
BINARYREADER_BASE
|
||||||
|
public:
|
||||||
|
|
||||||
|
SSFileReader(Uint8* data, Uint64 length);
|
||||||
|
SSFileReader(const std::string& filename);
|
||||||
|
|
||||||
|
SSFile* read();
|
||||||
|
};
|
||||||
|
} // io
|
||||||
|
} // zelda
|
||||||
|
|
||||||
|
#endif // __SSFILEREADER_HPP__
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef __SSFILEWRITER_HPP__
|
||||||
|
#define __SSFILEWRITER_HPP__
|
||||||
|
|
||||||
|
#include "BinaryWriter.hpp"
|
||||||
|
|
||||||
|
namespace zelda
|
||||||
|
{
|
||||||
|
class SSFile;
|
||||||
|
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
class SSFileWriter : public BinaryWriter
|
||||||
|
{
|
||||||
|
// Why does this fuck up my formatting in Qt Creator?
|
||||||
|
BINARYWRITER_BASE
|
||||||
|
public:
|
||||||
|
SSFileWriter(Uint8* data, Uint64 len);
|
||||||
|
SSFileWriter(const std::string& filename);
|
||||||
|
|
||||||
|
void write(SSFile* file);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // __SSFILEWRITER_HPP__
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef SSQUEST_HPP
|
||||||
|
#define SSQUEST_HPP
|
||||||
|
|
||||||
|
#include "ZQuestFile.hpp"
|
||||||
|
|
||||||
|
namespace zelda
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: Handle game specific data
|
||||||
|
class SSQuest : public ZQuestFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SSQuest(Uint8* data, Uint32 len);
|
||||||
|
|
||||||
|
// TODO: Is len really needed?
|
||||||
|
void setSkipData(const Uint8* data, Uint32 len = 0x24);
|
||||||
|
Uint8* skipData() const;
|
||||||
|
|
||||||
|
Uint32 skipLength() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Uint8* m_skipData;
|
||||||
|
Uint32 m_skipLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // zelda
|
||||||
|
#endif // SSQUEST_HPP
|
|
@ -122,6 +122,12 @@ public:
|
||||||
* \throw IOException
|
* \throw IOException
|
||||||
*/
|
*/
|
||||||
virtual Int8 readByte();
|
virtual Int8 readByte();
|
||||||
|
/*! \brief Reads a byte at the current position and advances the current position.
|
||||||
|
*
|
||||||
|
* \return Uint8* The buffer at the current position from the given length.
|
||||||
|
* \throw IOException
|
||||||
|
*/
|
||||||
|
virtual Uint8* readUBytes(Int64 length);
|
||||||
|
|
||||||
/*! \brief Reads a byte at the current position and advances the current position.
|
/*! \brief Reads a byte at the current position and advances the current position.
|
||||||
*
|
*
|
||||||
|
|
|
@ -30,6 +30,13 @@ enum Endian
|
||||||
LittleEndian, //!< Specifies that the Stream is Little Endian (LSB)
|
LittleEndian, //!< Specifies that the Stream is Little Endian (LSB)
|
||||||
BigEndian //!< Specifies that the Stream is Big Endian (MSB)
|
BigEndian //!< Specifies that the Stream is Big Endian (MSB)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Region
|
||||||
|
{
|
||||||
|
NTSCURegion,
|
||||||
|
NTSCJRegion,
|
||||||
|
PALRegion
|
||||||
|
};
|
||||||
} // zelda
|
} // zelda
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
14
libzelda.pro
14
libzelda.pro
|
@ -1,10 +1,12 @@
|
||||||
CONFIG += staticlib
|
CONFIG += staticlib
|
||||||
TEMPLATE=lib
|
TEMPLATE=lib
|
||||||
|
DESTDIR = ./
|
||||||
|
|
||||||
CONFIG(debug, debug|release){
|
CONFIG(debug, debug|release){
|
||||||
DEFINES += DEBUG
|
DEFINES += DEBUG
|
||||||
TARGET=zelda-d
|
TARGET=zelda-d
|
||||||
}
|
}
|
||||||
|
|
||||||
CONFIG(release, release|debug){
|
CONFIG(release, release|debug){
|
||||||
DEFINES -= DEBUG
|
DEFINES -= DEBUG
|
||||||
TARGET=zelda
|
TARGET=zelda
|
||||||
|
@ -52,7 +54,11 @@ HEADERS += \
|
||||||
include/ZQuestFileReader.hpp \
|
include/ZQuestFileReader.hpp \
|
||||||
include/Compression.hpp \
|
include/Compression.hpp \
|
||||||
include/WiiImage.hpp \
|
include/WiiImage.hpp \
|
||||||
include/ZQuestFile.hpp
|
include/ZQuestFile.hpp \
|
||||||
|
include/SSQuest.hpp \
|
||||||
|
include/SSFileWriter.hpp \
|
||||||
|
include/SSFileReader.hpp \
|
||||||
|
include/SSFile.hpp
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
src/utility.cpp \
|
src/utility.cpp \
|
||||||
|
@ -81,7 +87,11 @@ SOURCES += \
|
||||||
src/ZQuestFileReader.cpp \
|
src/ZQuestFileReader.cpp \
|
||||||
src/Compression.cpp \
|
src/Compression.cpp \
|
||||||
src/WiiImage.cpp \
|
src/WiiImage.cpp \
|
||||||
src/ZQuestFile.cpp
|
src/ZQuestFile.cpp \
|
||||||
|
src/SSQuest.cpp \
|
||||||
|
src/SSFileWriter.cpp \
|
||||||
|
src/SSFileReader.cpp \
|
||||||
|
src/SSFile.cpp
|
||||||
|
|
||||||
system("exec doxygen libzelda.conf")
|
system("exec doxygen libzelda.conf")
|
||||||
#system("cd doc/latex && make")
|
#system("cd doc/latex && make")
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include "SSFile.hpp"
|
||||||
|
#include "SSQuest.hpp"
|
||||||
|
#include "InvalidOperationException.hpp"
|
||||||
|
|
||||||
|
namespace zelda
|
||||||
|
{
|
||||||
|
|
||||||
|
SSFile::SSFile()
|
||||||
|
: m_numQuests(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SSFile::SSFile(std::vector<SSQuest*> quests)
|
||||||
|
: m_numQuests(0)
|
||||||
|
{
|
||||||
|
m_quests = quests;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSFile::~SSFile()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSFile::addQuest(zelda::SSQuest *q)
|
||||||
|
{
|
||||||
|
// Do not allow more than 3 quests
|
||||||
|
if (m_quests.size() >= 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_quests.push_back(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSQuest *SSFile::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<SSQuest*> SSFile::questList() const
|
||||||
|
{
|
||||||
|
return m_quests;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSFile::setRegion(Region region)
|
||||||
|
{
|
||||||
|
m_region = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
Region SSFile::region() const
|
||||||
|
{
|
||||||
|
return m_region;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // zelda
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include "SSFileReader.hpp"
|
||||||
|
#include "SSFile.hpp"
|
||||||
|
#include "SSQuest.hpp"
|
||||||
|
#include "InvalidOperationException.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace zelda
|
||||||
|
{
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
SSFileReader::SSFileReader(Uint8* data, Uint64 length)
|
||||||
|
: base(data, length)
|
||||||
|
{
|
||||||
|
base::setEndianess(BigEndian);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSFileReader::SSFileReader(const std::string& filename)
|
||||||
|
: base(filename)
|
||||||
|
{
|
||||||
|
base::setEndianess(BigEndian);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSFile* SSFileReader::read()
|
||||||
|
{
|
||||||
|
SSFile* file = NULL;
|
||||||
|
if (base::length() != 0xFBE0)
|
||||||
|
throw zelda::error::InvalidOperationException("SSFileReader::read -> File not the expected size of 0xFBE0");
|
||||||
|
|
||||||
|
Uint32 magic = base::readUInt32();
|
||||||
|
|
||||||
|
if (magic != SSFile::USMagic && magic != SSFile::JAMagic && magic != SSFile::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 SSFile;
|
||||||
|
file->setRegion((magic == SSFile::USMagic ? NTSCURegion : (magic == SSFile::JAMagic ? NTSCJRegion : PALRegion)));
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
SSQuest* q = new SSQuest((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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // io
|
||||||
|
} // zelda
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "SSFileWriter.hpp"
|
||||||
|
#include "SSFile.hpp"
|
||||||
|
#include "SSQuest.hpp"
|
||||||
|
|
||||||
|
namespace zelda
|
||||||
|
{
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
SSFileWriter::SSFileWriter(Uint8 *data, Uint64 len)
|
||||||
|
: base(data, len)
|
||||||
|
{
|
||||||
|
base::setEndianess(BigEndian);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSFileWriter::SSFileWriter(const std::string &filename)
|
||||||
|
: base(filename)
|
||||||
|
{
|
||||||
|
base::setEndianess(BigEndian);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSFileWriter::write(SSFile *file)
|
||||||
|
{
|
||||||
|
Uint32 magic = (file->region() == NTSCURegion ? SSFile::USMagic :
|
||||||
|
(file->region() == NTSCJRegion ? SSFile::JAMagic : SSFile::EUMagic));
|
||||||
|
|
||||||
|
base::writeUInt32(magic);
|
||||||
|
base::seek(0x1C, base::Beginning);
|
||||||
|
base::writeUInt32(0x1D);
|
||||||
|
|
||||||
|
std::vector<SSQuest*> quests = file->questList();
|
||||||
|
int i = 0;
|
||||||
|
for (SSQuest* 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
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "SSQuest.hpp"
|
||||||
|
|
||||||
|
namespace zelda
|
||||||
|
{
|
||||||
|
SSQuest::SSQuest(Uint8 *data, Uint32 len)
|
||||||
|
: ZQuestFile(ZQuestFile::SS, BigEndian, data, len),
|
||||||
|
m_skipData(NULL),
|
||||||
|
m_skipLength(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSQuest::setSkipData(const Uint8 *data, Uint32 len)
|
||||||
|
{
|
||||||
|
if (m_skipData)
|
||||||
|
{
|
||||||
|
delete[] m_skipData;
|
||||||
|
m_skipData = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_skipData = (Uint8*)data;
|
||||||
|
m_skipLength = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint8 *SSQuest::skipData() const
|
||||||
|
{
|
||||||
|
return m_skipData;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 SSQuest::skipLength() const
|
||||||
|
{
|
||||||
|
return m_skipLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // zelda
|
|
@ -180,6 +180,11 @@ Int8 Stream::readByte()
|
||||||
return *(Int8*)(m_data + m_position++);
|
return *(Int8*)(m_data + m_position++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Uint8 *Stream::readUBytes(Int64 length)
|
||||||
|
{
|
||||||
|
return (Uint8*)readBytes(length);
|
||||||
|
}
|
||||||
|
|
||||||
Int8* Stream::readBytes(Int64 length)
|
Int8* Stream::readBytes(Int64 length)
|
||||||
{
|
{
|
||||||
if (m_bitPosition > 0)
|
if (m_bitPosition > 0)
|
||||||
|
|
|
@ -81,6 +81,8 @@ void ZQuestFile::setData(Uint8* data, Uint32 length)
|
||||||
{
|
{
|
||||||
delete[] m_data;
|
delete[] m_data;
|
||||||
m_data = new Uint8[length];
|
m_data = new Uint8[length];
|
||||||
|
// Why is this memcpy needed?
|
||||||
|
// I get SIGABRT without it, need to research
|
||||||
memcpy(m_data, data, length);
|
memcpy(m_data, data, length);
|
||||||
m_length = length;
|
m_length = length;
|
||||||
}
|
}
|
||||||
|
@ -107,6 +109,7 @@ std::string ZQuestFile::gameString() const
|
||||||
|
|
||||||
void ZQuestFile::initGameStrings()
|
void ZQuestFile::initGameStrings()
|
||||||
{
|
{
|
||||||
|
// Populate game strings
|
||||||
m_gameStrings.push_back("No Game");
|
m_gameStrings.push_back("No Game");
|
||||||
m_gameStrings.push_back("Legend Of Zelda");
|
m_gameStrings.push_back("Legend Of Zelda");
|
||||||
m_gameStrings.push_back("Adventure of Link");
|
m_gameStrings.push_back("Adventure of Link");
|
||||||
|
@ -125,7 +128,7 @@ void ZQuestFile::initGameStrings()
|
||||||
m_gameStrings.push_back("Phantom Hourglass");
|
m_gameStrings.push_back("Phantom Hourglass");
|
||||||
m_gameStrings.push_back("Spirit Tracks");
|
m_gameStrings.push_back("Spirit Tracks");
|
||||||
m_gameStrings.push_back("Skyward Sword");
|
m_gameStrings.push_back("Skyward Sword");
|
||||||
m_gameStrings.push_back("A Link Between Worlds (Unreleased)");
|
m_gameStrings.push_back("A Link Between Worlds (Unreleased)"); // Probably should have this, but.....
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ ZQuestFile *ZQuestFileReader::read()
|
||||||
{
|
{
|
||||||
delete[] dst;
|
delete[] dst;
|
||||||
delete[] data;
|
delete[] data;
|
||||||
|
// TODO: Make proper exception
|
||||||
throw error::InvalidOperationException("ZQuestFileReader::read -> Error decompressing data");
|
throw error::InvalidOperationException("ZQuestFileReader::read -> Error decompressing data");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,12 +72,12 @@ void ZQuestFileWriter::write(ZQuestFile* quest, bool compress)
|
||||||
|
|
||||||
base::writeUInt32(quest->length());
|
base::writeUInt32(quest->length());
|
||||||
base::writeUInt32(quest->game());
|
base::writeUInt32(quest->game());
|
||||||
base::writeUInt16(quest->endian() == BigEndian ? 0xFEFF : 0xFFFE);
|
base::writeUInt16(quest->endian() == BigEndian ? 0xFFFE : 0xFEFF);
|
||||||
base::seek(0x0A);
|
base::seek(0x0A);
|
||||||
base::writeUBytes(questData, compLen);
|
base::writeUBytes(questData, compLen);
|
||||||
|
|
||||||
base::save();
|
base::save();
|
||||||
// Delete compressed data to preven memory leaks
|
// Delete compressed data to prevent memory leaks
|
||||||
if (questData != quest->data())
|
if (questData != quest->data())
|
||||||
{
|
{
|
||||||
delete[] questData;
|
delete[] questData;
|
||||||
|
|
Loading…
Reference in New Issue