cog/Frameworks/SSEQPlayer/SSEQPlayer/SDAT.cpp

94 lines
2.9 KiB
C++

/*
* SSEQ Player - SDAT structure
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
* Last modification on 2013-03-21
*
* Nintendo DS Nitro Composer (SDAT) Specification document found at
* http://www.feshrine.net/hacking/doc/nds-sdat.html
*/
#include "SDAT.h"
#include "NDSStdHeader.h"
#include "SYMBSection.h"
#include "INFOSection.h"
#include "FATSection.h"
#include "convert.h"
SDAT::SDAT(PseudoFile &file, uint32_t sseqToLoad) : sseq(), sbnk()
{
// Read sections
NDSStdHeader header;
header.Read(file);
header.Verify("SDAT", 0x0100FEFF);
uint32_t SYMBOffset = file.ReadLE<uint32_t>();
file.ReadLE<uint32_t>(); // SYMB size
uint32_t INFOOffset = file.ReadLE<uint32_t>();
file.ReadLE<uint32_t>(); // INFO size
uint32_t FATOffset = file.ReadLE<uint32_t>();
file.ReadLE<uint32_t>(); // FAT Size
SYMBSection symbSection;
if (SYMBOffset)
{
file.pos = SYMBOffset;
symbSection.Read(file);
}
file.pos = INFOOffset;
INFOSection infoSection;
infoSection.Read(file);
file.pos = FATOffset;
FATSection fatSection;
fatSection.Read(file);
if (infoSection.SEQrecord.entries.empty())
throw std::logic_error("No SSEQ records found in SDAT");
if (!infoSection.SEQrecord.entries.count(sseqToLoad))
throw std::range_error("SSEQ of " + stringify(sseqToLoad) + " is not found");
// Read SSEQ
if (infoSection.SEQrecord.entries.count(sseqToLoad))
{
uint16_t fileID = infoSection.SEQrecord.entries[sseqToLoad].fileID;
std::string name = "SSEQ" + NumToHexString(fileID).substr(2);
if (SYMBOffset)
name = NumToHexString(sseqToLoad).substr(6) + " - " + symbSection.SEQrecord.entries[sseqToLoad];
file.pos = fatSection.records[fileID].offset;
SSEQ *newSSEQ = new SSEQ(name);
newSSEQ->info = infoSection.SEQrecord.entries[sseqToLoad];
newSSEQ->Read(file);
this->sseq.reset(newSSEQ);
// Read SBNK for this SSEQ
uint16_t bank = newSSEQ->info.bank;
fileID = infoSection.BANKrecord.entries[bank].fileID;
name = "SBNK" + NumToHexString(fileID).substr(2);
if (SYMBOffset)
name = NumToHexString(bank).substr(2) + " - " + symbSection.BANKrecord.entries[bank];
file.pos = fatSection.records[fileID].offset;
SBNK *newSBNK = new SBNK(name);
newSSEQ->bank = newSBNK;
newSBNK->info = infoSection.BANKrecord.entries[bank];
newSBNK->Read(file);
this->sbnk.reset(newSBNK);
// Read SWARs for this SBNK
for (int i = 0; i < 4; ++i)
if (newSBNK->info.waveArc[i] != 0xFFFF)
{
uint16_t waveArc = newSBNK->info.waveArc[i];
fileID = infoSection.WAVEARCrecord.entries[waveArc].fileID;
name = "SWAR" + NumToHexString(fileID).substr(2);
if (SYMBOffset)
name = NumToHexString(waveArc).substr(2) + " - " + symbSection.WAVEARCrecord.entries[waveArc];
file.pos = fatSection.records[fileID].offset;
SWAR *newSWAR = new SWAR(name);
newSBNK->waveArc[i] = newSWAR;
newSWAR->info = infoSection.WAVEARCrecord.entries[waveArc];
newSWAR->Read(file);
this->swar[i].reset(newSWAR);
}
else
this->swar[i].release();
}
}