https://www.3dbrew.org/w/api.php?action=feedcontributions&user=Ethos8&feedformat=atom
3dbrew - User contributions [en]
2024-03-28T12:21:44Z
User contributions
MediaWiki 1.35.8
https://www.3dbrew.org/w/index.php?title=BCSAR&diff=21254
BCSAR
2020-05-26T04:31:24Z
<p>Ethos8: Added entry for the 24-byte padding to the FILE partition header anatomy table</p>
<hr />
<div>[[Category:File formats]]<br />
== Overview ==<br />
<br />
The BCSAR (Binary CTR Sound ARchive) format is the 3DS's equivalent of the Wii's BRSAR format. They're not the same structures, though, but they do have the same purpose.<br />
<br />
BCSAR are located in the RomFS, this is usually stored under "romfs:/sound/<name>.bcsar". This contains various audio formats, such as CSTM, CWSD, CSEQ, and CWAV.<br />
<br />
== BCSAR Header ==<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! OFFSET<br />
! SIZE<br />
! DESCRIPTION<br />
|-<br />
| 0x0<br />
| 0x4<br />
| MAGIC "CSAR"<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Byte order mark (0xFEFF = Big Endian, 0xFFFE = Little Endian)<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Length of BCSAR header<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Version<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Length of the entire BCSAR (starting from 0x0)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| Amount of main partitions in the BCSAR [STRG + INFO + FILE = 0x03 (= 3)]<br />
|-<br />
| 0x14<br />
| 0x4<br />
| STRG partition reference ID? (Always 0x2000)<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Location of STRG partition<br />
|-<br />
| 0x1C<br />
| 0x4<br />
| Length of STRG partition<br />
|-<br />
| 0x20<br />
| 0x4<br />
| INFO partition reference ID? (Always 0x2001)<br />
|-<br />
| 0x24<br />
| 0x4<br />
| Location of INFO partition<br />
|-<br />
| 0x28<br />
| 0x4<br />
| Length of INFO partition<br />
|-<br />
| 0x2C<br />
| 0x4<br />
| Main FILE partition reference ID? (Always 0x2002)<br />
|-<br />
| 0x30<br />
| 0x4<br />
| Location of main FILE partition<br />
|-<br />
| 0x34<br />
| 0x4<br />
| Length of main FILE partition<br />
|-<br />
| 0x38<br />
| 0x4<br />
| Reserved for 4th main partition location?<br />
|-<br />
| 0x3C<br />
| 0x4<br />
| Reserved for 4th main partition length?<br />
|-<br />
|}<br />
<br />
== Partitions ==<br />
<br />
=== STRG ===<br />
<br />
STRG contains the names of the audio files in the BCSAR.<br />
<br />
==== Header ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! OFFSET<br />
! SIZE<br />
! DESCRIPTION<br />
|-<br />
| 0x0<br />
| 0x4<br />
| MAGIC "STRG"<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Length of STRG partition (also in CSAR header)<br />
|-<br />
| 0x8<br />
| 0x4<br />
| String table type magic (always 0x2400)<br />
|-<br />
| 0xC<br />
| 0x4<br />
| This + 8 points to the string table (always 0x10)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| String table lookup type magic (always 0x2401)<br />
|-<br />
| 0x14<br />
| 0x4<br />
| This + 8 points to the string lookup table<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Filename count<br />
|-<br />
| 0x1C<br />
| 0xC * count<br />
| String offset table<br />
|-<br />
|}<br />
<br />
==== String offset table entry ====<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! OFFSET<br />
! SIZE<br />
! DESCRIPTION<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Type of the node (should be 0x1F01)<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Offset to data from the end of the STRG header (sizeof 0x18)<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Length of the data buffer (includes NUL terminator)<br />
|-<br />
|}<br />
<br />
Then every filename is rawly setted. You can set up a dictionary that contains, using a simple counter, the size of every filename in order. Then, using the same type of counter, get the values of the size of the filename in a correct order.<br />
<br />
==== String lookup table ====<br />
<br />
===== Header =====<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! OFFSET<br />
! SIZE<br />
! DESCRIPTION<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Index of the root entry<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Entry count<br />
|-<br />
| 0x8<br />
| 0x14 * count<br />
| Lookup entry<br />
|-<br />
|}<br />
<br />
===== Entry =====<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! OFFSET<br />
! SIZE<br />
! DESCRIPTION<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Nonzero if contains data<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Bit test condition (index = (this >> 3), bit = (~this & 7)), -1 if unused<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Fail condition leaf index (-1 if unused)<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Success condition leaf index (-1 if unused)<br />
|-<br />
| 0xC<br />
| 0x4<br />
| String lookup table index (-1 if unused)<br />
|-<br />
| 0x10<br />
| 0x3<br />
| 3-byte Resource ID, Little Endian (-1 if unused)<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Resource type (01=sound, 02=sound list, 03=sound bank, 04=sound player name?, 06=sound group, FF=unused)<br />
|-<br />
|}<br />
<br />
=== INFO ===<br />
<br />
INFO presumably contains information on the audio files? Possibly used to connect names from STRG to data from FILE?<br />
<br />
For now I only know some information in the header for this partition, but I'm working on figuring the rest out.<br />
<br />
==== Header ====<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! OFFSET<br />
! SIZE<br />
! DESCRIPTION<br />
|-<br />
| 0x0<br />
| 0x4<br />
| MAGIC "INFO"<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Length of INFO partition (also in CSAR header)<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Audio Table Reference ID (0x2100)<br />
|-<br />
| 0xC<br />
| 0x4<br />
| This + 8 points to the Audio Table<br />
|-<br />
| 0x10<br />
| 0x4<br />
| Set Table Reference ID (0x2104)<br />
|-<br />
| 0x14<br />
| 0x4<br />
| This + 8 points to the Set Table<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Bank Table Reference ID (0x2101)<br />
|-<br />
| 0x1C<br />
| 0x4<br />
| This + 8 points to the Bank Table<br />
|-<br />
| 0x20<br />
| 0x4<br />
| WAV Archive Table Reference ID (0x2103)<br />
|-<br />
| 0x24<br />
| 0x4<br />
| This + 8 points to the WAV Archive Table<br />
|-<br />
| 0x28<br />
| 0x4<br />
| Group Table Reference ID (0x2105)<br />
|-<br />
| 0x2C<br />
| 0x4<br />
| This + 8 points to the Group Table<br />
|-<br />
| 0x30<br />
| 0x4<br />
| Player Table Reference ID (0x2102)<br />
|-<br />
| 0x34<br />
| 0x4<br />
| This + 8 points to Player Table<br />
|-<br />
| 0x38<br />
| 0x4<br />
| FILE Table Reference ID (0x2106)<br />
|-<br />
| 0x3C<br />
| 0x4<br />
| This + 8 points to the FILE Table<br />
|-<br />
| 0x40<br />
| 0x4<br />
| Unknown Table Reference ID (0x220B)<br />
|-<br />
| 0x44<br />
| 0x4<br />
| This + 8 points to unknown<br />
|-<br />
|}<br />
<br />
==== Blocks ====<br />
<br />
Every offset in the header points to data similar to this:<br />
* 4byte length<br />
* length array of the below struct<br />
** u32 type<br />
** u32 offset relative to the address of the length field (beginning of the block)<br />
<br />
The data the offset points to is dependent on the type of the above struct:<br />
<br />
===== 0x2200 =====<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! OFFSET<br />
! SIZE<br />
! DESCRIPTION<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Sound player ID<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Type of the extended info<br />
|-<br />
| 0x10<br />
| 0x4<br />
| Offset to extended info *relative to the beginning of this struct*<br />
|-<br />
| 0x14<br />
| ???<br />
| Unknown...<br />
|-<br />
|}<br />
<br />
===== 0x2204 =====<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! OFFSET<br />
! SIZE<br />
! DESCRIPTION<br />
|-<br />
| 0x0<br />
| 0x4<br />
| First Sound ID in this sequence set<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Last Sound ID in this sequence set<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Type of the extended info<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Offset to extended info *relative to the beginning of this struct*<br />
|-<br />
| 0x10<br />
| 0x4<br />
| Type of the extended info<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Offset to extended info *relative to the beginning of this struct*<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x1C<br />
| 0x4<br />
| Unknown<br />
|-<br />
|}<br />
<br />
===== 0x2206 =====<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! OFFSET<br />
! SIZE<br />
! DESCRIPTION<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Type of the extended info<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Offset to extended info *relative to the beginning of this struct*<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x4<br />
| Unknown<br />
|-<br />
|}<br />
<br />
===== Table IDs =====<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! ID<br />
! NAME<br />
|-<br />
| 0x2200<br />
| Audio Table<br />
|-<br />
| 0x2204<br />
| Set Table<br />
|-<br />
| 0x2206<br />
| Bank Table<br />
|-<br />
| 0x2207<br />
| WAV Archive Table<br />
|-<br />
| 0x2208<br />
| Group Table<br />
|-<br />
| 0x2208<br />
| Player Table<br />
|-<br />
| 0x220A<br />
| FILE Table<br />
|-<br />
|}<br />
<br />
=== FILE ===<br />
<br />
FILE contains all of the audio data in the BCSAR.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! OFFSET<br />
! SIZE<br />
! DESCRIPTION<br />
|-<br />
| 0x0<br />
| 0x4<br />
| MAGIC "FILE"<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Length of FILE partition (also in CSAR header)<br />
|-<br />
| 0x8<br />
| 0x24<br />
| Padding<br />
|}<br />
<br />
There isn't a whole lot else I can document about the FILE partition, since the data in it will most definitely vary depending on the game. (since audio is more than likely to change in each game)<br />
<br />
There is no table in FILE so a different partition (presumably INFO) must be used to connect the data in FILE with the names from STRG.<br />
<br />
After some more research, there are multiple FILE partitions, but only 1 of them is the 'main' FILE partition (it's the one you get from the BCSAR header). The 'main' FILE partition contains all of the other sub FILE partitions.<br />
<br />
== Tools ==<br />
* vgmtoolbox's Advanced Cutter/Offset Finder tool can extract BCWAVs without filenames<br />
* [https://github.com/soneek/3DSUSoundArchiveTool 3DSUSoundArchiveTool] reference implementation of CSAR extraction</div>
Ethos8