Changes

Jump to navigation Jump to search
4,139 bytes added ,  21:55, 7 January 2021
Overview as a header seems redundant; put category at the end of the document
Line 1: Line 1: −
[[Category:File formats]]
+
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.
== Overview ==
  −
 
  −
The BCSAR (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.
     −
BCSAR are located in the RomFS, this is usually stored under "romfs:/sound/<name>.bcsar". This contains various audio formats, such as CSTM, CWSD, and CWAV.
+
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.
    
== BCSAR Header ==
 
== BCSAR Header ==
Line 40: Line 37:  
|  0x14
 
|  0x14
 
|  0x4
 
|  0x4
Partition header length [same for each partition? (ie STRG,INFO,and FILE header lengths)]
+
STRG partition reference ID? (Always 0x2000)
 
|-
 
|-
 
|  0x18
 
|  0x18
Line 52: Line 49:  
|  0x20
 
|  0x20
 
|  0x4
 
|  0x4
Unknown (always 0x01200000?)
+
INFO partition reference ID? (Always 0x2001)
 
|-
 
|-
 
|  0x24
 
|  0x24
Line 61: Line 58:  
|  0x4
 
|  0x4
 
|  Length of INFO partition
 
|  Length of INFO partition
 +
|-
 +
|  0x2C
 +
|  0x4
 +
|  Main FILE partition reference ID? (Always 0x2002)
 
|-
 
|-
 
|  0x30
 
|  0x30
Line 86: Line 87:  
STRG contains the names of the audio files in the BCSAR.
 
STRG contains the names of the audio files in the BCSAR.
   −
Header:
+
==== Header ====
 
   
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 101: Line 101:  
|  0x4
 
|  0x4
 
|  Length of STRG partition (also in CSAR header)
 
|  Length of STRG partition (also in CSAR header)
 +
|-
 +
|  0x8
 +
|  0x4
 +
|  String table type magic (always 0x2400)
 +
|-
 +
|  0xC
 +
|  0x4
 +
|  This + 8 points to the string table (always 0x10)
 +
|-
 +
|  0x10
 +
|  0x4
 +
|  String table lookup type magic (always 0x2401)
 +
|-
 +
|  0x14
 +
|  0x4
 +
|  This + 8 points to the string lookup table
 
|-
 
|-
 
|  0x18
 
|  0x18
 
|  0x4
 
|  0x4
Count of audio names (since each file should have a name you could also say this is essentially a file count)
+
Filename count
 +
|-
 +
|  0x1C
 +
|  0xC * count
 +
|  String offset table
 
|-
 
|-
 
|}
 
|}
   −
Then for each name:
+
==== String offset table entry ====
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 118: Line 138:  
|  0x0
 
|  0x0
 
|  0x4
 
|  0x4
|  Type of the file...?
+
|  Type of the node (should be 0x1F01)
 
|-
 
|-
 
|  0x4
 
|  0x4
 
|  0x4
 
|  0x4
|  Offset of the filename...?
+
|  Offset to data from the end of the STRG header (sizeof 0x18)
 
|-
 
|-
 
|  0x8
 
|  0x8
 
|  0x4
 
|  0x4
Size of the filename
+
Length of the data buffer (includes NUL terminator)
 
|-
 
|-
 
|}
 
|}
 +
 
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.
 
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.
 +
 +
==== String lookup table ====
 +
 +
===== Header =====
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
!  OFFSET
 +
!  SIZE
 +
!  DESCRIPTION
 +
|-
 +
|  0x0
 +
|  0x4
 +
|  Index of the root entry
 +
|-
 +
|  0x4
 +
|  0x4
 +
|  Entry count
 +
|-
 +
|  0x8
 +
|  0x14 * count
 +
|  Lookup entry
 +
|-
 +
|}
 +
 +
===== Entry =====
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
!  OFFSET
 +
!  SIZE
 +
!  DESCRIPTION
 +
|-
 +
|  0x0
 +
|  0x2
 +
|  Nonzero if contains data
 +
|-
 +
|  0x2
 +
|  0x2
 +
|  Bit test condition (index = (this >> 3), bit = (~this & 7)), -1 if unused
 +
|-
 +
|  0x4
 +
|  0x4
 +
|  Fail condition leaf index (-1 if unused)
 +
|-
 +
|  0x8
 +
|  0x4
 +
|  Success condition leaf index (-1 if unused)
 +
|-
 +
|  0xC
 +
|  0x4
 +
|  String lookup table index (-1 if unused)
 +
|-
 +
|  0x10
 +
|  0x3
 +
|  3-byte Resource ID, Little Endian (-1 if unused)
 +
|-
 +
|  0x13
 +
|  0x1
 +
|  Resource type (01=sound, 02=sound list, 03=sound bank, 04=sound player name?, 06=sound group, FF=unused)
 +
|-
 +
|}
 +
 
=== INFO ===
 
=== INFO ===
   Line 135: Line 219:     
For now I only know some information in the header for this partition, but I'm working on figuring the rest out.
 
For now I only know some information in the header for this partition, but I'm working on figuring the rest out.
 +
 +
==== Header ====
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 149: Line 235:  
|  0x4
 
|  0x4
 
|  Length of INFO partition (also in CSAR header)
 
|  Length of INFO partition (also in CSAR header)
 +
|-
 +
|  0x8
 +
|  0x4
 +
|  Audio Table Reference ID (0x2100)
 +
|-
 +
|  0xC
 +
|  0x4
 +
|  This + 8 points to the Audio Table
 +
|-
 +
|  0x10
 +
|  0x4
 +
|  Set Table Reference ID (0x2104)
 +
|-
 +
|  0x14
 +
|  0x4
 +
|  This + 8 points to the Set Table
 +
|-
 +
|  0x18
 +
|  0x4
 +
|  Bank Table Reference ID (0x2101)
 +
|-
 +
|  0x1C
 +
|  0x4
 +
|  This + 8 points to the Bank Table
 +
|-
 +
|  0x20
 +
|  0x4
 +
|  WAV Archive Table Reference ID (0x2103)
 +
|-
 +
|  0x24
 +
|  0x4
 +
|  This + 8 points to the WAV Archive Table
 +
|-
 +
|  0x28
 +
|  0x4
 +
|  Group Table Reference ID (0x2105)
 +
|-
 +
|  0x2C
 +
|  0x4
 +
|  This + 8 points to the Group Table
 +
|-
 +
|  0x30
 +
|  0x4
 +
|  Player Table Reference ID (0x2102)
 +
|-
 +
|  0x34
 +
|  0x4
 +
|  This + 8 points to Player Table
 +
|-
 +
|  0x38
 +
|  0x4
 +
|  FILE Table Reference ID (0x2106)
 +
|-
 +
|  0x3C
 +
|  0x4
 +
|  This + 8 points to the FILE Table
 +
|-
 +
|  0x40
 +
|  0x4
 +
|  Unknown Table Reference ID (0x220B)
 +
|-
 +
|  0x44
 +
|  0x4
 +
|  This + 8 points to unknown
 +
|-
 +
|}
 +
 +
==== Blocks ====
 +
 +
Every offset in the header points to data similar to this:
 +
* 4byte length
 +
* length array of the below struct
 +
** u32 type
 +
** u32 offset relative to the address of the length field (beginning of the block)
 +
 +
The data the offset points to is dependent on the type of the above struct:
 +
 +
===== 0x2200 =====
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
!  OFFSET
 +
!  SIZE
 +
!  DESCRIPTION
 +
|-
 +
|  0x0
 +
|  0x4
 +
|  Unknown
 +
|-
 +
|  0x4
 +
|  0x4
 +
|  Sound player ID
 +
|-
 +
|  0x8
 +
|  0x4
 +
|  Unknown
 +
|-
 +
|  0xC
 +
|  0x4
 +
|  Type of the extended info
 +
|-
 +
|  0x10
 +
|  0x4
 +
|  Offset to extended info *relative to the beginning of this struct*
 +
|-
 +
|  0x14
 +
|  ???
 +
|  Unknown...
 +
|-
 +
|}
 +
 +
===== 0x2204 =====
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
!  OFFSET
 +
!  SIZE
 +
!  DESCRIPTION
 +
|-
 +
|  0x0
 +
|  0x4
 +
|  First Sound ID in this sequence set
 +
|-
 +
|  0x4
 +
|  0x4
 +
|  Last Sound ID in this sequence set
 +
|-
 +
|  0x8
 +
|  0x4
 +
|  Type of the extended info
 +
|-
 +
|  0xC
 +
|  0x4
 +
|  Offset to extended info *relative to the beginning of this struct*
 +
|-
 +
|  0x10
 +
|  0x4
 +
|  Type of the extended info
 +
|-
 +
|  0x14
 +
|  0x4
 +
|  Offset to extended info *relative to the beginning of this struct*
 +
|-
 +
|  0x18
 +
|  0x4
 +
|  Unknown
 +
|-
 +
|  0x1C
 +
|  0x4
 +
|  Unknown
 +
|-
 +
|}
 +
 +
===== 0x2206 =====
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
!  OFFSET
 +
!  SIZE
 +
!  DESCRIPTION
 +
|-
 +
|  0x0
 +
|  0x4
 +
|  Unknown
 +
|-
 +
|  0x4
 +
|  0x4
 +
|  Type of the extended info
 +
|-
 +
|  0x8
 +
|  0x4
 +
|  Offset to extended info *relative to the beginning of this struct*
 +
|-
 +
|  0xC
 +
|  0x4
 +
|  Unknown
 +
|-
 +
|  0x10
 +
|  0x4
 +
|  Unknown
 +
|-
 +
|}
 +
 +
===== Table IDs =====
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
!  ID
 +
!  NAME
 +
|-
 +
|  0x2200
 +
|  Audio Table
 +
|-
 +
|  0x2204
 +
|  Set Table
 +
|-
 +
|  0x2206
 +
|  Bank Table
 +
|-
 +
|  0x2207
 +
|  WAV Archive Table
 +
|-
 +
|  0x2208
 +
|  Group Table
 +
|-
 +
|  0x2208
 +
|  Player Table
 +
|-
 +
|  0x220A
 +
|  FILE Table
 
|-
 
|-
 
|}
 
|}
Line 170: Line 466:  
|  Length of FILE partition (also in CSAR header)
 
|  Length of FILE partition (also in CSAR header)
 
|-
 
|-
 +
|  0x8
 +
|  0x24
 +
|  Padding
 
|}
 
|}
   Line 179: Line 478:     
== Tools ==
 
== Tools ==
* vgmtoolbox can extract CWAVs without filenames
+
* vgmtoolbox's Advanced Cutter/Offset Finder tool can extract BCWAVs without filenames
 +
* [https://github.com/soneek/3DSUSoundArchiveTool 3DSUSoundArchiveTool] reference implementation of CSAR extraction
 +
* [https://github.com/Gota7/Citric-Composer Citric Composer]
 +
 
 +
 
 +
[[Category:File formats]]
63

edits

Navigation menu