├── .gitignore ├── common ├── common.props ├── SSEQ.h ├── NDSStdHeader.h ├── SWAV.h ├── FATSection.h ├── SWAR.h ├── windowsh_wrapper.h ├── TagList.h ├── SYMBSection.h ├── NCSF.h ├── SSEQ.cpp ├── INFOSection.h ├── eqstr.h ├── ltstr.h ├── NDSStdHeader.cpp ├── SBNK.h ├── FATSection.cpp ├── SDAT.h ├── TagList.cpp ├── TimerPlayer.h ├── INFOEntry.h ├── TimerTrack.h ├── SWAR.cpp ├── SWAV.cpp ├── common.vcxproj.filters ├── INFOSection.cpp ├── SYMBSection.cpp ├── TimerChannel.h ├── common.vcxproj ├── INFOEntry.cpp ├── SBNK.cpp ├── TimerPlayer.cpp ├── NCSF.cpp ├── common.h └── win_dirent.h ├── NDStoNCSF ├── NDStoNCSF.vcxproj.filters └── NDStoNCSF.vcxproj ├── SDATStrip ├── SDATStrip.vcxproj.filters ├── SDATStrip.vcxproj └── SDATStrip.cpp ├── SDATtoNCSF ├── SDATtoNCSF.vcxproj.filters ├── SDATtoNCSF.vcxproj └── SDATtoNCSF.cpp ├── 2SFTagsToNCSF ├── 2SFTagsToNCSF.vcxproj.filters ├── 2SFTagsToNCSF.vcxproj └── 2SFTagsToNCSF.cpp ├── 2SFtoNCSF ├── 2SFtoNCSF.vcxproj.filters ├── 2SFtoNCSF.vcxproj └── 2SFtoNCSF.cpp ├── SDATStuff.sln ├── GNUmakefile └── README.txt /.gitignore: -------------------------------------------------------------------------------- 1 | Debug 2 | Release 3 | *.suo 4 | *.user -------------------------------------------------------------------------------- /common/common.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ZLIBFIXME 6 | 7 | 8 | 9 | 10 | 11 | $(zlibRootDir) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /common/SSEQ.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - SSEQ (Sequence) structure 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-12-08 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "INFOEntry.h" 13 | #include "common.h" 14 | 15 | struct SSEQ 16 | { 17 | std::string filename, origFilename; 18 | std::vector data; 19 | 20 | int32_t entryNumber; 21 | 22 | SSEQ(const std::string &fn = "", const std::string &origFn = ""); 23 | 24 | void Read(PseudoReadFile &file); 25 | }; 26 | -------------------------------------------------------------------------------- /common/NDSStdHeader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - Nintendo DS Standard Header structure 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-10-15 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "common.h" 13 | 14 | struct NDSStdHeader 15 | { 16 | int8_t type[4]; 17 | uint32_t magic; 18 | uint32_t fileSize; 19 | uint16_t size; 20 | uint16_t blocks; 21 | 22 | NDSStdHeader(); 23 | 24 | void Read(PseudoReadFile &file); 25 | void Verify(const std::string &typeToCheck, uint32_t magicToCheck) const; 26 | void Write(PseudoWrite &file) const; 27 | }; 28 | -------------------------------------------------------------------------------- /NDStoNCSF/NDStoNCSF.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /SDATStrip/SDATStrip.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /SDATtoNCSF/SDATtoNCSF.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /2SFTagsToNCSF/2SFTagsToNCSF.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /common/SWAV.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - SWAV (Waveform/Sample) structure 3 | * By Naram Qashat (CyberBotX) 4 | * Last modification on 2014-12-08 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "common.h" 13 | 14 | struct SWAV 15 | { 16 | uint8_t waveType; 17 | uint8_t loop; 18 | uint16_t sampleRate; 19 | uint16_t time; 20 | uint16_t origLoopOffset; 21 | uint32_t loopOffset; 22 | uint32_t origNonLoopLength; 23 | uint32_t nonLoopLength; 24 | std::vector origData; 25 | std::vector data; 26 | 27 | SWAV(); 28 | 29 | void Read(PseudoReadFile &file); 30 | void DecodeADPCM(uint32_t len); 31 | uint32_t Size() const; 32 | void Write(PseudoWrite &file) const; 33 | }; 34 | -------------------------------------------------------------------------------- /common/FATSection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - FAT (File Allocation Table) Section structures 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-10-15 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "common.h" 13 | 14 | struct FATRecord 15 | { 16 | uint32_t offset; 17 | uint32_t size; 18 | 19 | FATRecord(); 20 | 21 | void Read(PseudoReadFile &file); 22 | void Write(PseudoWrite &file) const; 23 | }; 24 | 25 | struct FATSection 26 | { 27 | int8_t type[4]; 28 | uint32_t size; 29 | uint32_t count; 30 | std::vector records; 31 | 32 | FATSection(); 33 | 34 | void Read(PseudoReadFile &file); 35 | uint32_t Size() const; 36 | void Write(PseudoWrite &file) const; 37 | }; 38 | -------------------------------------------------------------------------------- /common/SWAR.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - SWAR (Wave Archive) structures 3 | * By Naram Qashat (CyberBotX) 4 | * Last modification on 2014-12-08 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include "NDSStdHeader.h" 14 | #include "SWAV.h" 15 | #include "INFOEntry.h" 16 | #include "common.h" 17 | 18 | struct SWAR 19 | { 20 | typedef std::map> SWAVs; 21 | 22 | std::string filename; 23 | NDSStdHeader header; 24 | SWAVs swavs; 25 | 26 | int32_t entryNumber; 27 | 28 | SWAR(const std::string &fn = ""); 29 | SWAR(const SWAR &swar); 30 | SWAR &operator=(const SWAR &swar); 31 | 32 | void Read(PseudoReadFile &file); 33 | uint32_t Size() const; 34 | void Write(PseudoWrite &file) const; 35 | }; 36 | -------------------------------------------------------------------------------- /common/windowsh_wrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Wrapper for windows.h, found at: 3 | * http://learnwinapi.wordpress.com/2011/12/13/lesson-2-the-api-is-based-on-unicode/ 4 | */ 5 | 6 | #pragma once 7 | 8 | #ifdef _MBCS 9 | # error "_MBCS (multi-byte character set) is defined, but only Unicode is supported" 10 | #endif 11 | #undef _UNICODE 12 | #define _UNICODE // For [tchar.h] 13 | #undef UNICODE 14 | #define UNICODE // For [windows.h] 15 | 16 | #undef NOMINMAX 17 | #define NOMINMAX // C++ standard library compatibility 18 | #undef STRICT 19 | #define STRICT // C++ type-checking compatibility 20 | 21 | #ifndef _WIN32_WINNT 22 | # define _WIN32_WINNT _WIN32_WINNT_WIN2K 23 | #endif 24 | #ifdef _MSC_VER // Visual C++ only (the SDK is Visual C++ specific). 25 | # include // E.g. g++ 4.4.1 does not support this file/scheme. 26 | #endif 27 | 28 | #undef WIN32_LEAN_AND_MEAN 29 | #define WIN32_LEAN_AND_MEAN 30 | #include 31 | -------------------------------------------------------------------------------- /2SFtoNCSF/2SFtoNCSF.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /common/TagList.h: -------------------------------------------------------------------------------- 1 | /* 2 | * xSF Tag List 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-10-15 5 | * 6 | * Storage of tags from PSF-style files, specifications found at 7 | * http://wiki.neillcorlett.com/PSFTagFormat 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include "eqstr.h" 15 | #include "ltstr.h" 16 | 17 | class TagList 18 | { 19 | public: 20 | typedef std::map Tags; 21 | typedef std::vector TagsList; 22 | private: 23 | static eq_str eqstr; 24 | 25 | Tags tags; 26 | TagsList tagsOrder; 27 | public: 28 | TagList() : tags(), tagsOrder() { } 29 | const TagsList &GetKeys() const; 30 | TagsList GetTags() const; 31 | bool Empty() const; 32 | bool Exists(const std::string &name) const; 33 | std::string operator[](const std::string &name) const; 34 | std::string &operator[](const std::string &name); 35 | void CopyOverwriteExistingOnly(const TagList ©); 36 | void Remove(const std::string &name); 37 | void Clear(); 38 | }; 39 | -------------------------------------------------------------------------------- /common/SYMBSection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - SYMB (Symbol/Filename) Section structures 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-10-25 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "common.h" 13 | 14 | struct SYMBRecord 15 | { 16 | uint32_t count; 17 | std::vector entryOffsets; 18 | std::vector entries; 19 | 20 | SYMBRecord(); 21 | 22 | void Read(PseudoReadFile &file, uint32_t startOffset); 23 | uint32_t Size() const; 24 | void FixOffsets(uint32_t startOffset); 25 | void WriteHeader(PseudoWrite &file) const; 26 | void WriteData(PseudoWrite &file) const; 27 | }; 28 | 29 | struct SYMBSection 30 | { 31 | int8_t type[4]; 32 | uint32_t size; 33 | uint32_t recordOffsets[8]; 34 | SYMBRecord SEQrecord; 35 | SYMBRecord BANKrecord; 36 | SYMBRecord WAVEARCrecord; 37 | SYMBRecord PLAYERrecord; 38 | 39 | SYMBSection(); 40 | 41 | void Read(PseudoReadFile &file); 42 | uint32_t Size() const; 43 | void FixOffsets(); 44 | void Write(PseudoWrite &file) const; 45 | }; 46 | -------------------------------------------------------------------------------- /common/NCSF.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Common NCSF functions 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-10-15 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include "TagList.h" 12 | #include "SDAT.h" 13 | #include "common.h" 14 | 15 | typedef std::vector Files; 16 | 17 | void MakeNCSF(const std::string &filename, const std::vector &reservedSectionData, const std::vector &programSectionData, 18 | const std::vector &tags = std::vector()); 19 | void CheckForValidPSF(PseudoReadFile &file, uint8_t versionByte); 20 | std::vector GetProgramSectionFromPSF(PseudoReadFile &file, uint8_t versionByte, uint32_t programHeaderSize, uint32_t programSizeOffset, bool addHeaderSize = false); 21 | TagList GetTagsFromPSF(PseudoReadFile &file, uint8_t versionByte); 22 | Files GetFilesInDirectory(const std::string &path, const std::vector &extensions = std::vector()); 23 | void RemoveFiles(const Files &files); 24 | void GetTime(const std::string &filename, const SDAT *sdat, const SSEQ *sseq, TagList &tags, bool verbose, uint32_t numberOfLoops, uint32_t fadeLoop, uint32_t fadeOneShot); 25 | -------------------------------------------------------------------------------- /common/SSEQ.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - SSEQ (Sequence) structure 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-12-08 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #include "SSEQ.h" 11 | #include "NDSStdHeader.h" 12 | #include "SDAT.h" 13 | 14 | SSEQ::SSEQ(const std::string &fn, const std::string &origFn) : filename(fn), origFilename(origFn), data(), entryNumber(-1) 15 | { 16 | } 17 | 18 | void SSEQ::Read(PseudoReadFile &file) 19 | { 20 | uint32_t startOfSSEQ = file.pos; 21 | NDSStdHeader header; 22 | header.Read(file); 23 | try 24 | { 25 | header.Verify("SSEQ", 0x0100FEFF); 26 | } 27 | catch (const std::exception &) 28 | { 29 | if (SDAT::failOnMissingFiles) 30 | throw; 31 | else 32 | return; 33 | } 34 | int8_t type[4]; 35 | file.ReadLE(type); 36 | if (!VerifyHeader(type, "DATA")) 37 | throw std::runtime_error("SSEQ DATA structure invalid"); 38 | uint32_t size = file.ReadLE(); 39 | uint32_t dataOffset = file.ReadLE(); 40 | this->data.resize(size - 12, 0); 41 | file.pos = startOfSSEQ + dataOffset; 42 | file.ReadLE(this->data); 43 | } 44 | -------------------------------------------------------------------------------- /common/INFOSection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - INFO Section structures 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-10-25 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "INFOEntry.h" 13 | 14 | template struct INFORecord 15 | { 16 | uint32_t count, actualCount; 17 | std::vector entryOffsets; 18 | std::vector entries; 19 | 20 | INFORecord(); 21 | 22 | void Read(PseudoReadFile &file, uint32_t startOffset); 23 | uint32_t Size() const; 24 | void FixOffsets(uint32_t startOffset); 25 | void WriteHeader(PseudoWrite &file) const; 26 | void WriteData(PseudoWrite &file) const; 27 | }; 28 | 29 | struct INFOSection 30 | { 31 | int8_t type[4]; 32 | uint32_t size; 33 | uint32_t recordOffsets[8]; 34 | INFORecord SEQrecord; 35 | INFORecord BANKrecord; 36 | INFORecord WAVEARCrecord; 37 | INFORecord PLAYERrecord; 38 | 39 | INFOSection(); 40 | 41 | void Read(PseudoReadFile &file); 42 | uint32_t Size() const; 43 | void FixOffsets(); 44 | void Write(PseudoWrite &file) const; 45 | }; 46 | -------------------------------------------------------------------------------- /common/eqstr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Case-insensitive string equality 3 | * Last modification on 2014-10-15 4 | * 5 | * Based on "How to do case-insensitive string comparison" 6 | * By Matt Austern 7 | * http://lafstern.org/matt/col2_new.pdf 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | struct eq_str : std::binary_function 19 | { 20 | struct eq_char : std::binary_function 21 | { 22 | const char *tab; 23 | eq_char(const char *t) : tab(t) { } 24 | bool operator()(char x, char y) const { return this->tab[x - CHAR_MIN] == this->tab[y - CHAR_MIN]; } 25 | }; 26 | 27 | char tab[CHAR_MAX - CHAR_MIN + 1]; 28 | 29 | eq_str(const std::locale &L = std::locale::classic()) 30 | { 31 | for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) 32 | this->tab[i - CHAR_MIN] = static_cast(i); 33 | std::use_facet>(L).toupper(this->tab, this->tab + (CHAR_MAX - CHAR_MIN + 1)); 34 | } 35 | 36 | bool operator()(const std::string &x, const std::string &y) const 37 | { 38 | return x.length() == y.length() && std::equal(x.begin(), x.end(), y.begin(), eq_char(this->tab)); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /common/ltstr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Case-insensitive string comparison 3 | * Last modification on 2014-10-15 4 | * 5 | * Based on "How to do case-insensitive string comparison" 6 | * By Matt Austern 7 | * http://lafstern.org/matt/col2_new.pdf 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | struct lt_str : std::binary_function 19 | { 20 | struct lt_char : std::binary_function 21 | { 22 | const char *tab; 23 | lt_char(const char *t) : tab(t) { } 24 | bool operator()(char x, char y) const { return this->tab[x - CHAR_MIN] < this->tab[y - CHAR_MIN]; } 25 | }; 26 | 27 | char tab[CHAR_MAX - CHAR_MIN + 1]; 28 | 29 | lt_str(const std::locale &L = std::locale::classic()) 30 | { 31 | for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) 32 | this->tab[i - CHAR_MIN] = static_cast(i); 33 | std::use_facet>(L).toupper(this->tab, this->tab + (CHAR_MAX - CHAR_MIN + 1)); 34 | } 35 | 36 | bool operator()(const std::string &x, const std::string &y) const 37 | { 38 | return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), lt_char(this->tab)); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /common/NDSStdHeader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - Nintendo DS Standard Header structure 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2013-03-25 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #include "NDSStdHeader.h" 11 | 12 | NDSStdHeader::NDSStdHeader() : magic(0), fileSize(0), size(0), blocks(0) 13 | { 14 | memset(this->type, 0, sizeof(this->type)); 15 | } 16 | 17 | void NDSStdHeader::Read(PseudoReadFile &file) 18 | { 19 | file.ReadLE(this->type); 20 | this->magic = file.ReadLE(); 21 | this->fileSize = file.ReadLE(); 22 | this->size = file.ReadLE(); 23 | this->blocks = file.ReadLE(); // # of blocks 24 | } 25 | 26 | void NDSStdHeader::Verify(const std::string &typeToCheck, uint32_t magicToCheck) const 27 | { 28 | if (!VerifyHeader(this->type, typeToCheck) || this->magic != magicToCheck) 29 | throw std::runtime_error("NDS Standard Header for " + typeToCheck + " invalid"); 30 | } 31 | 32 | void NDSStdHeader::Write(PseudoWrite &file) const 33 | { 34 | file.WriteLE(this->type); 35 | file.WriteLE(this->magic); 36 | file.WriteLE(this->fileSize); 37 | file.WriteLE(this->size); 38 | file.WriteLE(this->blocks); 39 | } 40 | -------------------------------------------------------------------------------- /common/SBNK.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - SBNK (Sound Bank) structures 3 | * By Naram Qashat (CyberBotX) 4 | * Last modification on 2014-12-08 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "NDSStdHeader.h" 13 | #include "INFOEntry.h" 14 | #include "common.h" 15 | 16 | struct SBNKInstrumentRange 17 | { 18 | uint8_t lowNote; 19 | uint8_t highNote; 20 | uint16_t record; 21 | uint16_t swav; 22 | uint16_t swar; 23 | uint8_t noteNumber; 24 | uint8_t attackRate; 25 | uint8_t decayRate; 26 | uint8_t sustainLevel; 27 | uint8_t releaseRate; 28 | uint8_t pan; 29 | 30 | SBNKInstrumentRange(uint8_t lowerNote, uint8_t upperNote, int recordType); 31 | 32 | void Read(PseudoReadFile &file); 33 | void Write(PseudoWrite &file) const; 34 | }; 35 | 36 | struct SBNKInstrument 37 | { 38 | uint8_t record; 39 | uint16_t offset; 40 | uint8_t unknown; 41 | std::vector ranges; 42 | 43 | SBNKInstrument(); 44 | 45 | void Read(PseudoReadFile &file, uint32_t startOffset); 46 | uint32_t Size() const; 47 | uint16_t FixOffset(uint16_t newOffset); 48 | void WriteHeader(PseudoWrite &file) const; 49 | void WriteData(PseudoWrite &file) const; 50 | }; 51 | 52 | struct SBNK 53 | { 54 | std::string filename; 55 | NDSStdHeader header; 56 | uint32_t count; 57 | std::vector instruments; 58 | 59 | int32_t entryNumber; 60 | 61 | SBNK(const std::string &fn = ""); 62 | 63 | void Read(PseudoReadFile &file); 64 | uint32_t Size() const; 65 | uint32_t DataSize() const; 66 | void FixOffsets(); 67 | void Write(PseudoWrite &file) const; 68 | }; 69 | -------------------------------------------------------------------------------- /common/FATSection.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - FAT (File Allocation Table) Section structures 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2013-03-25 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #include "FATSection.h" 11 | 12 | FATRecord::FATRecord() : offset(0), size(0) 13 | { 14 | } 15 | 16 | void FATRecord::Read(PseudoReadFile &file) 17 | { 18 | this->offset = file.ReadLE(); 19 | this->size = file.ReadLE(); 20 | uint32_t reserved[2]; 21 | file.ReadLE(reserved); 22 | } 23 | 24 | void FATRecord::Write(PseudoWrite &file) const 25 | { 26 | file.WriteLE(this->offset); 27 | file.WriteLE(this->size); 28 | uint32_t reserved[2] = { }; 29 | file.WriteLE(reserved); 30 | } 31 | 32 | FATSection::FATSection() : size(0), count(0), records() 33 | { 34 | memcpy(this->type, "FAT ", sizeof(this->type)); 35 | } 36 | 37 | void FATSection::Read(PseudoReadFile &file) 38 | { 39 | file.ReadLE(this->type); 40 | if (!VerifyHeader(this->type, "FAT ")) 41 | throw std::runtime_error("SDAT FAT Section invalid"); 42 | this->size = file.ReadLE(); 43 | this->count = file.ReadLE(); 44 | this->records.resize(this->count); 45 | for (uint32_t i = 0; i < this->count; ++i) 46 | this->records[i].Read(file); 47 | } 48 | 49 | uint32_t FATSection::Size() const 50 | { 51 | return 12 + 16 * this->count; // type + size + count + records * 16 (size of each record) 52 | } 53 | 54 | void FATSection::Write(PseudoWrite &file) const 55 | { 56 | file.WriteLE(this->type); 57 | file.WriteLE(this->size); 58 | file.WriteLE(this->count); 59 | for (uint32_t i = 0; i < this->count; ++i) 60 | this->records[i].Write(file); 61 | } 62 | -------------------------------------------------------------------------------- /common/SDAT.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - SDAT structure 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-12-08 5 | * 6 | * Nintendo DS Nitro Composer (SDAT) Specification document found at 7 | * http://www.feshrine.net/hacking/doc/nds-sdat.html 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "NDSStdHeader.h" 13 | #include "SYMBSection.h" 14 | #include "INFOSection.h" 15 | #include "FATSection.h" 16 | #include "SSEQ.h" 17 | #include "SBNK.h" 18 | #include "SWAR.h" 19 | #include "common.h" 20 | 21 | struct SDAT 22 | { 23 | typedef std::vector> SSEQList; 24 | typedef std::vector> SBNKList; 25 | typedef std::vector> SWARList; 26 | 27 | static bool failOnMissingFiles; 28 | 29 | std::string filename; 30 | NDSStdHeader header; 31 | uint32_t SYMBOffset; 32 | uint32_t SYMBSize; 33 | uint32_t INFOOffset; 34 | uint32_t INFOSize; 35 | uint32_t FATOffset; 36 | uint32_t FATSize; 37 | uint32_t FILEOffset; 38 | uint32_t FILESize; 39 | 40 | SYMBSection symbSection; 41 | INFOSection infoSection; 42 | FATSection fatSection; 43 | 44 | bool symbSectionNeedsCleanup; 45 | uint16_t count; 46 | 47 | SSEQList SSEQs; 48 | SBNKList SBNKs; 49 | SWARList SWARs; 50 | 51 | SDAT(); 52 | SDAT(const SDAT &sdat); 53 | SDAT &operator=(const SDAT &sdat); 54 | 55 | void Read(const std::string &fn, PseudoReadFile &file, bool shouldFailOnMissingFiles = true); 56 | void Write(PseudoWrite &file) const; 57 | 58 | SDAT MakeFromSSEQ(uint16_t SSEQNumber) const; 59 | 60 | SDAT &operator+=(const SDAT &other); 61 | void Strip(const IncOrExc &includesAndExcludes, bool verbose, bool removeExcluded = true); 62 | void StripBanksAndWaveArcs(); 63 | void FixOffsetsAndSizes(); 64 | 65 | SSEQList::iterator GetNonConstSSEQ(const SSEQ *sseq); 66 | SBNKList::iterator GetNonConstSBNK(const SBNK *sbnk); 67 | SWARList::iterator GetNonConstSWAR(const SWAR *swar); 68 | }; 69 | -------------------------------------------------------------------------------- /common/TagList.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xSF Tag List 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-11-12 5 | * 6 | * Storage of tags from PSF-style files, specifications found at 7 | * http://wiki.neillcorlett.com/PSFTagFormat 8 | */ 9 | 10 | #include 11 | #include "TagList.h" 12 | 13 | eq_str TagList::eqstr; 14 | 15 | auto TagList::GetKeys() const -> const TagsList & 16 | { 17 | return this->tagsOrder; 18 | } 19 | 20 | auto TagList::GetTags() const -> TagsList 21 | { 22 | TagsList allTags; 23 | std::for_each(this->tagsOrder.begin(), this->tagsOrder.end(), [&](const std::string &tag) 24 | { 25 | allTags.push_back(tag + "=" + this->tags.find(tag)->second); 26 | }); 27 | return allTags; 28 | } 29 | 30 | bool TagList::Empty() const 31 | { 32 | return this->tags.empty(); 33 | } 34 | 35 | bool TagList::Exists(const std::string &name) const 36 | { 37 | return std::find_if(this->tagsOrder.begin(), this->tagsOrder.end(), std::bind2nd(TagList::eqstr, name)) != this->tagsOrder.end(); 38 | } 39 | 40 | std::string TagList::operator[](const std::string &name) const 41 | { 42 | auto tag = this->tags.find(name); 43 | if (tag == this->tags.end()) 44 | return ""; 45 | return tag->second; 46 | } 47 | 48 | std::string &TagList::operator[](const std::string &name) 49 | { 50 | auto tag = std::find_if(this->tagsOrder.begin(), this->tagsOrder.end(), std::bind2nd(TagList::eqstr, name)); 51 | if (tag == this->tagsOrder.end()) 52 | { 53 | this->tagsOrder.push_back(name); 54 | this->tags[name] = ""; 55 | } 56 | return this->tags[name]; 57 | } 58 | 59 | void TagList::CopyOverwriteExistingOnly(const TagList ©) 60 | { 61 | std::for_each(copy.tagsOrder.begin(), copy.tagsOrder.end(), [&](const std::string &tag) { (*this)[tag] = copy[tag]; }); 62 | } 63 | 64 | void TagList::Remove(const std::string &name) 65 | { 66 | auto tagOrder = std::find_if(this->tagsOrder.begin(), this->tagsOrder.end(), std::bind2nd(TagList::eqstr, name)); 67 | if (tagOrder != this->tagsOrder.end()) 68 | this->tagsOrder.erase(tagOrder); 69 | if (this->tags.count(name)) 70 | this->tags.erase(name); 71 | } 72 | 73 | void TagList::Clear() 74 | { 75 | this->tagsOrder.clear(); 76 | this->tags.clear(); 77 | } 78 | -------------------------------------------------------------------------------- /common/TimerPlayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SDAT - Timer Player structure 3 | * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] 4 | * Last modification on 2014-12-08 5 | * 6 | * Adapted from source code of FeOS Sound System 7 | * By fincs 8 | * https://github.com/fincs/FSS 9 | * 10 | * This has been modified in order to be able to provide timing for an SSEQ. 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include "TimerTrack.h" 17 | #include "TimerChannel.h" 18 | #include "SSEQ.h" 19 | #include "SBNK.h" 20 | #include "SWAR.h" 21 | #ifdef _WIN32 22 | # include "windowsh_wrapper.h" 23 | #else 24 | # include 25 | # include 26 | # include 27 | #endif 28 | 29 | enum TimeType 30 | { 31 | LOOP, 32 | END 33 | }; 34 | 35 | struct Time 36 | { 37 | double time; 38 | TimeType type; 39 | 40 | Time(double tim = 0.0, TimeType typ = LOOP) : time(tim), type(typ) 41 | { 42 | } 43 | }; 44 | 45 | const int TRACKCOUNT = 16; 46 | const int MAXTRACKS = 32; 47 | 48 | enum { TYPE_PCM, TYPE_PSG, TYPE_NOISE }; 49 | 50 | struct TimerPlayer 51 | { 52 | uint8_t prio, nTracks; 53 | uint16_t tempo, tempoCount, tempoRate; 54 | int16_t masterVol, sseqVol; 55 | 56 | TimerTrack tracks[MAXTRACKS]; 57 | std::vector