mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-30 17:24:31 +01:00
Fix some custom/buggy .dsp
This commit is contained in:
parent
0709ad1d87
commit
edcffe05c4
@ -1,11 +1,12 @@
|
|||||||
#include "meta.h"
|
#include "meta.h"
|
||||||
#include "../layout/layout.h"
|
#include "../layout/layout.h"
|
||||||
#include "../coding/coding.h"
|
#include "../coding/coding.h"
|
||||||
|
#include "../util/endianness.h"
|
||||||
|
|
||||||
|
|
||||||
/* If these variables are packed properly in the struct (one after another)
|
/* If these variables are packed properly in the struct (one after another)
|
||||||
* then this is actually how they are laid out in the file, albeit big-endian */
|
* then this is actually how they are laid out in the file, albeit big-endian */
|
||||||
struct dsp_header {
|
typedef struct {
|
||||||
uint32_t sample_count; /* 0x00 */
|
uint32_t sample_count; /* 0x00 */
|
||||||
uint32_t nibble_count; /* 0x04 (includes frame headers) */
|
uint32_t nibble_count; /* 0x04 (includes frame headers) */
|
||||||
uint32_t sample_rate; /* 0x08 (generally 22/32/44/48kz but games like Wario World set 32028hz to adjust for GC's rate) */
|
uint32_t sample_rate; /* 0x08 (generally 22/32/44/48kz but games like Wario World set 32028hz to adjust for GC's rate) */
|
||||||
@ -26,13 +27,13 @@ struct dsp_header {
|
|||||||
uint16_t block_size; /* 0x4c */
|
uint16_t block_size; /* 0x4c */
|
||||||
/* padding/reserved up to 0x60, DSPADPCM.exe from GC adds garbage here (uninitialized MSVC memory?)
|
/* padding/reserved up to 0x60, DSPADPCM.exe from GC adds garbage here (uninitialized MSVC memory?)
|
||||||
* [ex. Batallion Wars (GC), Timesplitters 2 (GC)], 0xcccc...cccc with DSPADPCMD */
|
* [ex. Batallion Wars (GC), Timesplitters 2 (GC)], 0xcccc...cccc with DSPADPCMD */
|
||||||
};
|
} dsp_header_t;
|
||||||
|
|
||||||
/* read and do basic validations to the above struct */
|
/* read and do basic validations to the above struct */
|
||||||
static bool read_dsp_header_endian(struct dsp_header *header, off_t offset, STREAMFILE* sf, int big_endian) {
|
static bool read_dsp_header_endian(dsp_header_t* header, off_t offset, STREAMFILE* sf, bool big_endian) {
|
||||||
uint32_t (*get_u32)(const uint8_t*) = big_endian ? get_u32be : get_u32le;
|
get_u32_t get_u32 = big_endian ? get_u32be : get_u32le;
|
||||||
uint16_t (*get_u16)(const uint8_t*) = big_endian ? get_u16be : get_u16le;
|
get_u16_t get_u16 = big_endian ? get_u16be : get_u16le;
|
||||||
int16_t (*get_s16)(const uint8_t*) = big_endian ? get_s16be : get_s16le;
|
get_s16_t get_s16 = big_endian ? get_s16be : get_s16le;
|
||||||
uint8_t buf[0x60];
|
uint8_t buf[0x60];
|
||||||
int zero_coefs;
|
int zero_coefs;
|
||||||
|
|
||||||
@ -71,9 +72,11 @@ static bool read_dsp_header_endian(struct dsp_header *header, off_t offset, STRE
|
|||||||
header->loop_start_offset = get_u32(buf+0x10);
|
header->loop_start_offset = get_u32(buf+0x10);
|
||||||
header->loop_end_offset = get_u32(buf+0x14);
|
header->loop_end_offset = get_u32(buf+0x14);
|
||||||
|
|
||||||
|
//TODO: test if games react to changed initial offset
|
||||||
|
/* Dr. Muto uses 0, and some custom Metroid Prime loop start, so probably ignored by the hardware */
|
||||||
header->initial_offset = get_u32(buf+0x18);
|
header->initial_offset = get_u32(buf+0x18);
|
||||||
if (header->initial_offset != 2 && header->initial_offset != 0)
|
if (header->initial_offset != 2 && header->initial_offset != 0 && header->initial_offset != header->loop_start_offset)
|
||||||
goto fail; /* Dr. Muto uses 0 */
|
goto fail;
|
||||||
|
|
||||||
zero_coefs = 0;
|
zero_coefs = 0;
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
@ -110,10 +113,10 @@ static bool read_dsp_header_endian(struct dsp_header *header, off_t offset, STRE
|
|||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static int read_dsp_header_be(struct dsp_header *header, off_t offset, STREAMFILE* file) {
|
static int read_dsp_header_be(dsp_header_t *header, off_t offset, STREAMFILE* file) {
|
||||||
return read_dsp_header_endian(header, offset, file, 1);
|
return read_dsp_header_endian(header, offset, file, 1);
|
||||||
}
|
}
|
||||||
static int read_dsp_header_le(struct dsp_header *header, off_t offset, STREAMFILE* file) {
|
static int read_dsp_header_le(dsp_header_t *header, off_t offset, STREAMFILE* file) {
|
||||||
return read_dsp_header_endian(header, offset, file, 0);
|
return read_dsp_header_endian(header, offset, file, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +157,7 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta* dspm) {
|
|||||||
VGMSTREAM* vgmstream = NULL;
|
VGMSTREAM* vgmstream = NULL;
|
||||||
int i, j;
|
int i, j;
|
||||||
int loop_flag;
|
int loop_flag;
|
||||||
struct dsp_header ch_header[COMMON_DSP_MAX_CHANNELS];
|
dsp_header_t ch_header[COMMON_DSP_MAX_CHANNELS];
|
||||||
|
|
||||||
|
|
||||||
if (dspm->channels > dspm->max_channels)
|
if (dspm->channels > dspm->max_channels)
|
||||||
@ -306,7 +309,7 @@ fail:
|
|||||||
/* .dsp - standard mono dsp as generated by DSPADPCM.exe */
|
/* .dsp - standard mono dsp as generated by DSPADPCM.exe */
|
||||||
VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) {
|
VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) {
|
||||||
VGMSTREAM* vgmstream = NULL;
|
VGMSTREAM* vgmstream = NULL;
|
||||||
struct dsp_header header;
|
dsp_header_t header;
|
||||||
const size_t header_size = 0x60;
|
const size_t header_size = 0x60;
|
||||||
off_t start_offset;
|
off_t start_offset;
|
||||||
int i, channels;
|
int i, channels;
|
||||||
@ -338,7 +341,7 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) {
|
|||||||
// (but .dsp is the common case, so it'd be slower)
|
// (but .dsp is the common case, so it'd be slower)
|
||||||
{
|
{
|
||||||
int ko;
|
int ko;
|
||||||
struct dsp_header header2;
|
dsp_header_t header2;
|
||||||
|
|
||||||
/* ignore headers one after another */
|
/* ignore headers one after another */
|
||||||
ko = !read_dsp_header_be(&header2, header_size, sf);
|
ko = !read_dsp_header_be(&header2, header_size, sf);
|
||||||
@ -427,7 +430,7 @@ fail:
|
|||||||
/* .dsp - little endian dsp, possibly main Switch .dsp [LEGO Worlds (Switch)] */
|
/* .dsp - little endian dsp, possibly main Switch .dsp [LEGO Worlds (Switch)] */
|
||||||
VGMSTREAM* init_vgmstream_ngc_dsp_std_le(STREAMFILE* sf) {
|
VGMSTREAM* init_vgmstream_ngc_dsp_std_le(STREAMFILE* sf) {
|
||||||
VGMSTREAM* vgmstream = NULL;
|
VGMSTREAM* vgmstream = NULL;
|
||||||
struct dsp_header header;
|
dsp_header_t header;
|
||||||
const size_t header_size = 0x60;
|
const size_t header_size = 0x60;
|
||||||
off_t start_offset;
|
off_t start_offset;
|
||||||
int i, channels;
|
int i, channels;
|
||||||
@ -450,7 +453,7 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std_le(STREAMFILE* sf) {
|
|||||||
* In many cases these will pass all the other checks, including the
|
* In many cases these will pass all the other checks, including the
|
||||||
* predictor/scale check if the first byte is 0 */
|
* predictor/scale check if the first byte is 0 */
|
||||||
{
|
{
|
||||||
struct dsp_header header2;
|
dsp_header_t header2;
|
||||||
int ko;
|
int ko;
|
||||||
|
|
||||||
ko = !read_dsp_header_le(&header2, header_size, sf);
|
ko = !read_dsp_header_le(&header2, header_size, sf);
|
||||||
@ -510,7 +513,7 @@ fail:
|
|||||||
/* .dsp - standard multi-channel dsp as generated by DSPADPCM.exe (later revisions) */
|
/* .dsp - standard multi-channel dsp as generated by DSPADPCM.exe (later revisions) */
|
||||||
VGMSTREAM* init_vgmstream_ngc_mdsp_std(STREAMFILE* sf) {
|
VGMSTREAM* init_vgmstream_ngc_mdsp_std(STREAMFILE* sf) {
|
||||||
VGMSTREAM* vgmstream = NULL;
|
VGMSTREAM* vgmstream = NULL;
|
||||||
struct dsp_header header;
|
dsp_header_t header;
|
||||||
const size_t header_size = 0x60;
|
const size_t header_size = 0x60;
|
||||||
off_t start_offset;
|
off_t start_offset;
|
||||||
int i, c, channels;
|
int i, c, channels;
|
||||||
|
Loading…
Reference in New Issue
Block a user