Fix doku, Fix bcstm, Add default constructors to BCWAV

- Removed DSP_ADPCM throw error
- Only load ADPCM data if the file uses ADPCM
- Add BCWAV cleanup
This commit is contained in:
2025-12-04 21:17:51 +01:00
parent fb8f275ebb
commit 2d771a27be
6 changed files with 70 additions and 79 deletions

View File

@@ -35,7 +35,7 @@ Not all Planned formates are listed here yet
| Format | State | Notes | | Format | State | Notes |
| ------ | ----- | ----- | | ------ | ----- | ----- |
| 3dsx | Basic Loading and Viewing of Meta Data Smdh | | | 3dsx | Basic Loading and Viewing of Meta Data Smdh | |
| bcstm | Loading of almost every Data | Not capable of playing them yet (prefetch kernel panic) | | bcstm | Loading of almost every Data | Fully done and playable by BCSTM-Player |
| bcwav | Basic Loading (not tested yet) | Not finished yet | | bcwav | Basic Loading (not tested yet) | Not finished yet |
| bclim | Nothing done yet (Started creating header) | | | bclim | Nothing done yet (Started creating header) | |
| lz11 | Encoder done, Decoder missing | Files are bit diffrent to the ones bannertool generates (don't know why) | | lz11 | Encoder done, Decoder missing | Files are bit diffrent to the ones bannertool generates (don't know why) |

View File

@@ -162,12 +162,13 @@ using u16 = unsigned short; // or uint16_t
using u8 = unsigned char; // or uint8_t using u8 = unsigned char; // or uint8_t
``` ```
## Tools / Devices / File SOurces used for research ## Tools / Devices / File Sources used for research
| Name | Description | | Name | Description |
|---|---| |---|---|
| Visual Studio Code | Used for creating ctrff c++ code for bcstm | | Visual Studio Code | Used for creating ctrff c++ code for bcstm |
| ImHex | Used to Analyze the Hex Code of the bcstm Files | | ImHex | Used to Analyze the Hex Code of the bcstm Files |
| LoopingAudioConverter | Used to create some files for testing |
| Citra | Fast way to generate Log files when developing ctrff | | Citra | Fast way to generate Log files when developing ctrff |
| ctrff-cli | Tool to generate Debug Output on Desktop OS like seen in BCSTM-Player File inspector | | ctrff-cli | Tool to generate Debug Output on Desktop OS like seen in BCSTM-Player File inspector |
| New 3ds XL | Testing on Real Hardware (BCSTM-Player) | | New 3ds XL | Testing on Real Hardware (BCSTM-Player) |
@@ -175,4 +176,4 @@ using u8 = unsigned char; // or uint8_t
| CTGP 7 | Used to get Test files | | CTGP 7 | Used to get Test files |
| Super Mario Maker 3ds (Cartridge) | Used to get Test files | | Super Mario Maker 3ds (Cartridge) | Used to get Test files |
| Mario and Luigi Bowsers inside story (Cartridge) | Used to get Test files | | Mario and Luigi Bowsers inside story (Cartridge) | Used to get Test files |
| Donkey Kong Country Returns 3D | Used to get Test files | | Donkey Kong Country Returns 3D (Cardridge) | Used to get Test files |

View File

@@ -13,8 +13,7 @@
- 2.3 [Reference Types](#reference-types) - 2.3 [Reference Types](#reference-types)
- 3 [Block Header](#block-header) - 3 [Block Header](#block-header)
- 4 [Info Block](#info-block) - 4 [Info Block](#info-block)
- 4.1 [Stream Info](#stream-info) - 4.1 [Channel Info](#channel-info)
- 4.2 [Channel Info](#channel-info)
- 5 [DSP ADPCM Info](#dsp-adpcm-info) - 5 [DSP ADPCM Info](#dsp-adpcm-info)
- 5.1 [DSP ADPCM Param](#dsp-adpcm-param) - 5.1 [DSP ADPCM Param](#dsp-adpcm-param)
- 5.2 [DSP ADPCM Context](#dsp-adpcm-context) - 5.2 [DSP ADPCM Context](#dsp-adpcm-context)
@@ -91,27 +90,6 @@ All Reference Offsets at the beginning of Info Block are Relative to the **Infob
| 0x18 | 4 | [u32](#u32) | Reserved | | 0x18 | 4 | [u32](#u32) | Reserved |
| 0x18 | 8 | [Reference Table](#reference-table) | Channel Info Reference Table | | 0x18 | 8 | [Reference Table](#reference-table) | Channel Info Reference Table |
### Stream Info
| Offset | Size | Datatype | Description |
|---|---|---|---|
| 0x00 | 1 | [u8](#u8) | Encoding |
| 0x01 | 1 | [u8](#u8) | Loop `1 == true -- 0 == false` |
| 0x02 | 1 | [u8](#u8) | Num Channels |
| 0x03 | 1 | [u8](#u8) | Padding |
| 0x04 | 4 | [u32](#u32) | Sample Rate |
| 0x04 | 4 | [u32](#u32) | Loop Start |
| 0x04 | 4 | [u32](#u32) | Loop End |
| 0x04 | 4 | [u32](#u32) | Sample Blocks |
| 0x04 | 4 | [u32](#u32) | Sample Block Size |
| 0x04 | 4 | [u32](#u32) | Sample Block Samples |
| 0x04 | 4 | [u32](#u32) | Last Sample Block Size |
| 0x04 | 4 | [u32](#u32) | Last Sample Block Samples |
| 0x04 | 4 | [u32](#u32) | Last Sample Block Padded Size |
| 0x04 | 4 | [u32](#u32) | Seek Data Size |
| 0x04 | 4 | [u32](#u32) | Seek Interval Samples |
| 0x04 | 4 | [Reference](#reference) | Sample Data Reference |
### Channel Info ### Channel Info
| Offset | Size | Datatype | Description | | Offset | Size | Datatype | Description |
@@ -162,17 +140,18 @@ using u16 = unsigned short; // or uint16_t
using u8 = unsigned char; // or uint8_t using u8 = unsigned char; // or uint8_t
``` ```
## Tools / Devices / File SOurces used for research ## Tools / Devices / File Sources used for research
| Name | Description | | Name | Description |
|---|---| |---|---|
| Visual Studio Code | Used for creating ctrff c++ code for bcstm | | Visual Studio Code | Used for creating ctrff c++ code for bcstm |
| ImHex | Used to Analyze the Hex Code of the bcstm Files | | ImHex | Used to Analyze the Hex Code of the bcstm Files |
| Citra | Fast way to generate Log files when developing ctrff | | Citra | Fast way to generate Log files when developing ctrff |
| LoopingAudioConverter | Used to create some files for testing |
| ctrff-cli | Tool to generate Debug Output on Desktop OS like seen in BCSTM-Player File inspector | | ctrff-cli | Tool to generate Debug Output on Desktop OS like seen in BCSTM-Player File inspector |
| New 3ds XL | Testing on Real Hardware (BCSTM-Player) | | New 3ds XL | Testing on Real Hardware (BCSTM-Player) |
| Mario Kart 7 (Cartridge) | Used to get Test files | | Mario Kart 7 (Cartridge) | Used to get Test files |
| CTGP 7 | Used to get Test files | | CTGP 7 | Used to get Test files |
| Super Mario Maker 3ds (Cartridge) | Used to get Test files | | Super Mario Maker 3ds (Cartridge) | Used to get Test files |
| Mario and Luigi Bowsers inside story (Cartridge) | Used to get Test files | | Mario and Luigi Bowsers inside story (Cartridge) | Used to get Test files |
| Donkey Kong Country Returns 3D | Used to get Test files | | Donkey Kong Country Returns 3D (Cardridge) | Used to get Test files |

View File

@@ -39,46 +39,39 @@ class CTRFF_API BCWAV {
}; };
struct Reference { struct Reference {
Reference() : TypeID(0), Padding(0), Offset(0) {}
PD::u16 TypeID; PD::u16 TypeID;
PD::u16 Padding; PD::u16 Padding;
PD::u32 Offset; /** null -> uint32_max */ PD::u32 Offset; /** null -> uint32_max */
}; };
struct ReferenceTable { struct ReferenceTable {
ReferenceTable() : Count(0) {}
PD::u32 Count; PD::u32 Count;
std::vector<Reference> Refs; std::vector<Reference> Refs;
}; };
struct SizedReference { struct SizedReference {
SizedReference() : Size(0) {}
Reference Ref; Reference Ref;
PD::u32 Size; PD::u32 Size;
}; };
struct StreamInfo {
PD::u8 Encoding;
PD::u8 Loop;
PD::u8 ChannelCount;
PD::u8 Padding;
PD::u32 SampleRate;
PD::u32 LoopStartFrame;
PD::u32 LoopEndFrame;
PD::u32 SampleBlockNum;
PD::u32 SampleBlockSize;
PD::u32 SampleBlockSampleNum;
PD::u32 LastSampleBlockSize;
PD::u32 LastSampleBlockSampleNum;
PD::u32 LastSampleBlockPaddedSize;
PD::u32 SeekDataSize;
PD::u32 SeekIntervalSampleNum;
Reference SampleDataRef;
};
struct BlockHeader { struct BlockHeader {
BlockHeader() : Magic(0), Size(0) {}
PD::u32 Magic; PD::u32 Magic;
PD::u32 Size; PD::u32 Size;
}; };
struct InfoBlock { struct InfoBlock {
InfoBlock()
: Encoding(0),
Loop(0),
Padding(0),
SampleRate(0),
LoopStartFrame(0),
LoopEndFrame(0),
Reserved(0) {}
BlockHeader Header; BlockHeader Header;
PD::u8 Encoding; PD::u8 Encoding;
PD::u8 Loop; PD::u8 Loop;
@@ -92,6 +85,11 @@ class CTRFF_API BCWAV {
}; };
struct DataBlock { struct DataBlock {
DataBlock() {
for (int i = 0; i < 3; i++) {
Padding[i] = 0;
}
}
BlockHeader Header; BlockHeader Header;
PD::u32 Padding[3]; PD::u32 Padding[3];
std::vector<PD::u8> Data; std::vector<PD::u8> Data;
@@ -101,6 +99,11 @@ class CTRFF_API BCWAV {
PD::u16 Coefficients[0x10]; PD::u16 Coefficients[0x10];
}; };
struct DSP_ADPCM_Context { struct DSP_ADPCM_Context {
DSP_ADPCM_Context()
: PredictorScale(0),
Reserved(0),
PreviousSample(0),
SecondPreviousSample(0) {}
PD::u8 PredictorScale; PD::u8 PredictorScale;
PD::u8 Reserved; PD::u8 Reserved;
PD::u16 PreviousSample; PD::u16 PreviousSample;
@@ -108,6 +111,7 @@ class CTRFF_API BCWAV {
}; };
struct DSP_ADPCM_Info { struct DSP_ADPCM_Info {
DSP_ADPCM_Info() : Padding(0) {}
DSP_ADPCM_Param Param; DSP_ADPCM_Param Param;
DSP_ADPCM_Context Context; DSP_ADPCM_Context Context;
DSP_ADPCM_Context LoopContext; DSP_ADPCM_Context LoopContext;
@@ -115,6 +119,14 @@ class CTRFF_API BCWAV {
}; };
struct Header { struct Header {
Header()
: Magic(0),
Endianness(Little),
HeaderSize(0),
Version(0),
FileSize(0),
NumBlocks(0),
Reserved(0) {}
PD::u32 Magic; /** CWAV */ PD::u32 Magic; /** CWAV */
PD::u16 Endianness = Little; /** Default */ PD::u16 Endianness = Little; /** Default */
PD::u16 HeaderSize; /** Header Size probably */ PD::u16 HeaderSize; /** Header Size probably */

View File

@@ -61,9 +61,6 @@ CTRFF_API void BCSTM::ReadInfoBlock(InfoBlock& block) {
ReadReference(block.TrackInfoTabRef); ReadReference(block.TrackInfoTabRef);
ReadReference(block.ChannelInfoTabRef); ReadReference(block.ChannelInfoTabRef);
pReader.Read(block.StreamInfo.Encoding); pReader.Read(block.StreamInfo.Encoding);
if (block.StreamInfo.Encoding != DSP_ADPCM) {
throw std::runtime_error("Only DSP ADPCM is supported yet!");
}
pReader.Read(block.StreamInfo.Loop); pReader.Read(block.StreamInfo.Loop);
pReader.Read(block.StreamInfo.ChannelCount); pReader.Read(block.StreamInfo.ChannelCount);
pReader.Read(block.StreamInfo.Padding); pReader.Read(block.StreamInfo.Padding);
@@ -99,6 +96,7 @@ CTRFF_API void BCSTM::ReadInfoBlock(InfoBlock& block) {
ReadReference(r); ReadReference(r);
block.ChannelInfoRefs.push_back(r); block.ChannelInfoRefs.push_back(r);
} }
if (block.StreamInfo.Encoding == DSP_ADPCM) {
for (size_t i = 0; i < block.ChannelInfoRefs.size(); i++) { for (size_t i = 0; i < block.ChannelInfoRefs.size(); i++) {
size_t off = pInfoBlockRef.Ref.Offset; size_t off = pInfoBlockRef.Ref.Offset;
off += sizeof(BlockHeader); off += sizeof(BlockHeader);
@@ -110,6 +108,7 @@ CTRFF_API void BCSTM::ReadInfoBlock(InfoBlock& block) {
pReader.ReadEx(t); /** This Section gets read normally */ pReader.ReadEx(t); /** This Section gets read normally */
pDSP_ADPCM_Info.push_back(t); pDSP_ADPCM_Info.push_back(t);
} }
}
} }
CTRFF_API void BCSTM::ReadSeekBlock(SD_Block& block) { CTRFF_API void BCSTM::ReadSeekBlock(SD_Block& block) {

View File

@@ -69,6 +69,7 @@ CTRFF_API void BCWAV::ReadInfoBlock(InfoBlock& block) {
ReadReference(r); ReadReference(r);
block.ChannelInfoRefs.push_back(r); block.ChannelInfoRefs.push_back(r);
} }
if (block.Encoding == DSP_ADPCM) {
for (size_t i = 0; i < block.ChannelInfoRefs.size(); i++) { for (size_t i = 0; i < block.ChannelInfoRefs.size(); i++) {
size_t off = pInfoBlockRef.Ref.Offset; size_t off = pInfoBlockRef.Ref.Offset;
off += sizeof(BlockHeader); off += sizeof(BlockHeader);
@@ -79,6 +80,7 @@ CTRFF_API void BCWAV::ReadInfoBlock(InfoBlock& block) {
pReader.ReadEx(t); /** This Section gets read normally */ pReader.ReadEx(t); /** This Section gets read normally */
pDSP_ADPCM_Info.push_back(t); pDSP_ADPCM_Info.push_back(t);
} }
}
} }
CTRFF_API void BCWAV::ReadReferenceTab(ReferenceTable& tab) { CTRFF_API void BCWAV::ReadReferenceTab(ReferenceTable& tab) {
@@ -102,14 +104,8 @@ CTRFF_API void BCWAV::ReadGotoBeginning(bool use_loop_beg) {
/** Shift to loop start if enabled */ /** Shift to loop start if enabled */
if (use_loop_beg) { if (use_loop_beg) {
// off += GetNumBlocks() * GetNumChannels() * GetLoopStart(); // off += GetNumBlocks() * GetNumChannels() * GetLoopStart();
// off += GetNumChannels() * pInfoBlock.StreamInfo.LoopStartFrame;
} }
// block_size * channel_count * loop_start
try {
pFile.seekg(off, std::ios::beg); pFile.seekg(off, std::ios::beg);
} catch (const std::exception& e) {
throw std::runtime_error(e.what());
}
if (pFile.tellg() > pHeader.FileSize) { if (pFile.tellg() > pHeader.FileSize) {
throw std::runtime_error("BCWAV: Seeked Out of range!"); throw std::runtime_error("BCWAV: Seeked Out of range!");
} }
@@ -134,9 +130,13 @@ CTRFF_API void BCWAV::CleanUp() {
throw std::runtime_error(e.what()); throw std::runtime_error(e.what());
} }
} }
pInfoBlock.ChannelInfoRefs.clear(); pInfoBlock = InfoBlock();
pInfoBlock.ChannelInfoTab.Refs.clear(); pHeader = Header();
pInfoBlock.ChannelInfoTab.Count = 0; pInfoBlockRef = SizedReference();
pDataBlockRef = SizedReference();
// Does not get read idk why i added it
// cause it needs to be streamed
pDataBlock = DataBlock();
pDSP_ADPCM_Info.clear(); pDSP_ADPCM_Info.clear();
} }
} // namespace ctrff } // namespace ctrff