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 \
|
||||
private: \
|
||||
typedef zelda::io::BinaryReader base;
|
||||
|
||||
#endif // BINARYREADER_BASE
|
||||
|
||||
#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
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
|
|
@ -30,6 +30,13 @@ enum Endian
|
|||
LittleEndian, //!< Specifies that the Stream is Little Endian (LSB)
|
||||
BigEndian //!< Specifies that the Stream is Big Endian (MSB)
|
||||
};
|
||||
|
||||
enum Region
|
||||
{
|
||||
NTSCURegion,
|
||||
NTSCJRegion,
|
||||
PALRegion
|
||||
};
|
||||
} // zelda
|
||||
#endif
|
||||
|
||||
|
|
14
libzelda.pro
14
libzelda.pro
|
@ -1,10 +1,12 @@
|
|||
CONFIG += staticlib
|
||||
TEMPLATE=lib
|
||||
DESTDIR = ./
|
||||
|
||||
CONFIG(debug, debug|release){
|
||||
DEFINES += DEBUG
|
||||
TARGET=zelda-d
|
||||
}
|
||||
|
||||
CONFIG(release, release|debug){
|
||||
DEFINES -= DEBUG
|
||||
TARGET=zelda
|
||||
|
@ -52,7 +54,11 @@ HEADERS += \
|
|||
include/ZQuestFileReader.hpp \
|
||||
include/Compression.hpp \
|
||||
include/WiiImage.hpp \
|
||||
include/ZQuestFile.hpp
|
||||
include/ZQuestFile.hpp \
|
||||
include/SSQuest.hpp \
|
||||
include/SSFileWriter.hpp \
|
||||
include/SSFileReader.hpp \
|
||||
include/SSFile.hpp
|
||||
|
||||
SOURCES += \
|
||||
src/utility.cpp \
|
||||
|
@ -81,7 +87,11 @@ SOURCES += \
|
|||
src/ZQuestFileReader.cpp \
|
||||
src/Compression.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("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++);
|
||||
}
|
||||
|
||||
Uint8 *Stream::readUBytes(Int64 length)
|
||||
{
|
||||
return (Uint8*)readBytes(length);
|
||||
}
|
||||
|
||||
Int8* Stream::readBytes(Int64 length)
|
||||
{
|
||||
if (m_bitPosition > 0)
|
||||
|
|
|
@ -81,6 +81,8 @@ void ZQuestFile::setData(Uint8* data, Uint32 length)
|
|||
{
|
||||
delete[] m_data;
|
||||
m_data = new Uint8[length];
|
||||
// Why is this memcpy needed?
|
||||
// I get SIGABRT without it, need to research
|
||||
memcpy(m_data, data, length);
|
||||
m_length = length;
|
||||
}
|
||||
|
@ -107,6 +109,7 @@ std::string ZQuestFile::gameString() const
|
|||
|
||||
void ZQuestFile::initGameStrings()
|
||||
{
|
||||
// Populate game strings
|
||||
m_gameStrings.push_back("No Game");
|
||||
m_gameStrings.push_back("Legend Of Zelda");
|
||||
m_gameStrings.push_back("Adventure of Link");
|
||||
|
@ -125,7 +128,7 @@ void ZQuestFile::initGameStrings()
|
|||
m_gameStrings.push_back("Phantom Hourglass");
|
||||
m_gameStrings.push_back("Spirit Tracks");
|
||||
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[] data;
|
||||
// TODO: Make proper exception
|
||||
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->game());
|
||||
base::writeUInt16(quest->endian() == BigEndian ? 0xFEFF : 0xFFFE);
|
||||
base::writeUInt16(quest->endian() == BigEndian ? 0xFFFE : 0xFEFF);
|
||||
base::seek(0x0A);
|
||||
base::writeUBytes(questData, compLen);
|
||||
|
||||
base::save();
|
||||
// Delete compressed data to preven memory leaks
|
||||
// Delete compressed data to prevent memory leaks
|
||||
if (questData != quest->data())
|
||||
{
|
||||
delete[] questData;
|
||||
|
|
Loading…
Reference in New Issue