-
Notifications
You must be signed in to change notification settings - Fork 3
/
SDAT.cpp
93 lines (86 loc) · 2.94 KB
/
SDAT.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
* 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();
}
}