mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 06:50:20 +01:00
commit
c7afd0d72a
@ -191,7 +191,7 @@ left together.
|
||||
|
||||
Similarly some formats split header and/or data in separate files (.sgh+sgd,
|
||||
.wav.str+.wav, (file)_L.dsp+(file)_R.dsp, etc). vgmstream will also detect
|
||||
and use those as needed and must be tegether, even if only one of the two
|
||||
and use those as needed and must be together, even if only one of the two
|
||||
will be used to play.
|
||||
|
||||
.pos is a small file with 32 bit little endian values: loop start sample
|
||||
@ -308,7 +308,7 @@ the format defined.
|
||||
|
||||
|
||||
## Supported codec types
|
||||
Quick list of codecs vgmstream supports, including many obscure ones that
|
||||
Quick list of codecs vgmstream supports, including many obscure ones that
|
||||
are used in few games.
|
||||
|
||||
- PCM 16-bit
|
||||
@ -322,7 +322,7 @@ are used in few games.
|
||||
- Nintendo AFC ADPCM
|
||||
- ITU-T G.721
|
||||
- CD-ROM XA ADPCM
|
||||
- Sony PSX ADPCM a.k.a VAG (standard, badflags, configurable)
|
||||
- Sony PSX ADPCM a.k.a VAG (standard, badflags, configurable, Pivotal)
|
||||
- Sony HEVAG
|
||||
- Electronic Arts EA-XA (stereo, mono, Maxis)
|
||||
- Electronic Arts EA-XAS (v0, v1)
|
||||
|
@ -630,7 +630,7 @@ int main(int argc, char **argv) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
again:
|
||||
again:
|
||||
|
||||
{
|
||||
struct params default_par = DEFAULT_PARAMS;
|
||||
@ -639,6 +639,12 @@ int main(int argc, char **argv) {
|
||||
|
||||
while ((opt = getopt(argc, argv, "-D:F:L:M:S:b:d:f:o:@:hrv")) != -1) {
|
||||
switch (opt) {
|
||||
case 1:
|
||||
if (play_file(optarg, &par)) {
|
||||
status = 1;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case '@':
|
||||
if (play_playlist(optarg, &par)) {
|
||||
status = 1;
|
||||
@ -689,9 +695,12 @@ int main(int argc, char **argv) {
|
||||
verbose = 1;
|
||||
break;
|
||||
default:
|
||||
VGM_LOG("vgmstream123: unknown opt %x", opt);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* try to read infile here in case getopt didn't pass "1" to the above switch I guess */
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
@ -707,7 +716,7 @@ int main(int argc, char **argv) {
|
||||
goto again;
|
||||
}
|
||||
|
||||
done:
|
||||
done:
|
||||
|
||||
if (device)
|
||||
ao_close(device);
|
||||
|
@ -83,6 +83,7 @@ size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
|
||||
/* psx_decoder */
|
||||
void decode_psx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int is_badflags);
|
||||
void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size);
|
||||
void decode_psx_pivotal(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size);
|
||||
int ps_find_loop_offsets(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t * out_loop_start, int32_t * out_loop_end);
|
||||
int ps_find_loop_offsets_full(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t * out_loop_start, int32_t * out_loop_end);
|
||||
size_t ps_find_padding(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int discard_empty);
|
||||
@ -108,10 +109,10 @@ void decode_ea_xas_v0(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspa
|
||||
void decode_ea_xas_v1(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
|
||||
/* sdx2_decoder */
|
||||
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_cbd2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_cbd2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
|
||||
/* ws_decoder */
|
||||
void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
|
@ -3,11 +3,11 @@
|
||||
|
||||
/* PS-ADPCM table, defined as rational numbers (as in the spec) */
|
||||
static const double ps_adpcm_coefs_f[5][2] = {
|
||||
{ 0.0 , 0.0 },
|
||||
{ 60.0 / 64.0 , 0.0 },
|
||||
{ 115.0 / 64.0 , -52.0 / 64.0 },
|
||||
{ 98.0 / 64.0 , -55.0 / 64.0 },
|
||||
{ 122.0 / 64.0 , -60.0 / 64.0 },
|
||||
{ 0.0 , 0.0 }, //{ 0.0 , 0.0 },
|
||||
{ 0.9375 , 0.0 }, //{ 60.0 / 64.0 , 0.0 },
|
||||
{ 1.796875 , -0.8125 }, //{ 115.0 / 64.0 , -52.0 / 64.0 },
|
||||
{ 1.53125 , -0.859375 }, //{ 98.0 / 64.0 , -55.0 / 64.0 },
|
||||
{ 1.90625 , -0.9375 }, //{ 122.0 / 64.0 , -60.0 / 64.0 },
|
||||
};
|
||||
|
||||
/* PS-ADPCM table, defined as spec_coef*64 (for int implementations) */
|
||||
@ -101,7 +101,7 @@ void decode_psx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing
|
||||
|
||||
|
||||
/* PS-ADPCM with configurable frame size and no flag (int math version).
|
||||
* Found in some PC/PS3 games (FF XI in sizes 3/5/9/41, Afrika in size 4, Blur/James Bond in size 33, etc).
|
||||
* Found in some PC/PS3 games (FF XI in sizes 0x3/0x5/0x9/0x41, Afrika in size 0x4, Blur/James Bond in size 0x33, etc).
|
||||
*
|
||||
* Uses int math to decode, which seems more likely (based on FF XI PC's code in Moogle Toolbox). */
|
||||
void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size) {
|
||||
@ -114,7 +114,7 @@ void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int c
|
||||
|
||||
/* external interleave (variable size), mono */
|
||||
bytes_per_frame = frame_size;
|
||||
samples_per_frame = (bytes_per_frame - 0x01) * 2; /* always 28 */
|
||||
samples_per_frame = (bytes_per_frame - 0x01) * 2;
|
||||
frames_in = first_sample / samples_per_frame;
|
||||
first_sample = first_sample % samples_per_frame;
|
||||
|
||||
@ -152,6 +152,56 @@ void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int c
|
||||
stream->adpcm_history2_32 = hist2;
|
||||
}
|
||||
|
||||
/* PS-ADPCM from Pivotal games, exactly like psx_cfg but with float math (reverse engineered from the exe) */
|
||||
void decode_psx_pivotal(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size) {
|
||||
off_t frame_offset;
|
||||
int i, frames_in, sample_count = 0;
|
||||
size_t bytes_per_frame, samples_per_frame;
|
||||
uint8_t coef_index, shift_factor;
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int32_t hist2 = stream->adpcm_history2_32;
|
||||
float scale;
|
||||
|
||||
/* external interleave (variable size), mono */
|
||||
bytes_per_frame = frame_size;
|
||||
samples_per_frame = (bytes_per_frame - 0x01) * 2;
|
||||
frames_in = first_sample / samples_per_frame;
|
||||
first_sample = first_sample % samples_per_frame;
|
||||
|
||||
/* parse frame header */
|
||||
frame_offset = stream->offset + bytes_per_frame*frames_in;
|
||||
coef_index = ((uint8_t)read_8bit(frame_offset+0x00,stream->streamfile) >> 4) & 0xf;
|
||||
shift_factor = ((uint8_t)read_8bit(frame_offset+0x00,stream->streamfile) >> 0) & 0xf;
|
||||
|
||||
VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %x\n", (uint32_t)frame_offset);
|
||||
if (coef_index > 5) /* just in case */
|
||||
coef_index = 5;
|
||||
if (shift_factor > 12) /* same */
|
||||
shift_factor = 12;
|
||||
scale = (float)(1.0 / (double)(1 << shift_factor));
|
||||
|
||||
/* decode nibbles */
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
||||
int32_t sample = 0;
|
||||
uint8_t nibbles = (uint8_t)read_8bit(frame_offset+0x01+i/2,stream->streamfile);
|
||||
|
||||
sample = !(i&1) ? /* low nibble first */
|
||||
(nibbles >> 0) & 0x0f :
|
||||
(nibbles >> 4) & 0x0f;
|
||||
sample = (int16_t)((sample << 12) & 0xf000); /* 16b sign extend + default scale */
|
||||
sample = sample*scale + ps_adpcm_coefs_f[coef_index][0]*hist1 + ps_adpcm_coefs_f[coef_index][1]*hist2; /* actually substracts negative coefs but whatevs */
|
||||
|
||||
outbuf[sample_count] = clamp16(sample);
|
||||
sample_count += channelspacing;
|
||||
|
||||
hist2 = hist1;
|
||||
hist1 = sample; /* not clamped but no difference */
|
||||
}
|
||||
|
||||
stream->adpcm_history1_32 = hist1;
|
||||
stream->adpcm_history2_32 = hist2;
|
||||
}
|
||||
|
||||
|
||||
/* Find loop samples in PS-ADPCM data and return if the file loops.
|
||||
*
|
||||
@ -339,7 +389,8 @@ size_t ps_bytes_to_samples(size_t bytes, int channels) {
|
||||
}
|
||||
|
||||
size_t ps_cfg_bytes_to_samples(size_t bytes, size_t frame_size, int channels) {
|
||||
return bytes / channels / frame_size * 28;
|
||||
int samples_per_frame = (frame_size - 0x01) * 2;
|
||||
return bytes / channels / frame_size * samples_per_frame;
|
||||
}
|
||||
|
||||
/* test PS-ADPCM frames for correctness */
|
||||
|
@ -5,114 +5,112 @@
|
||||
/* SDX2 - 2:1 Squareroot-delta-exact compression */
|
||||
/* CBD2 - 2:1 Cuberoot-delta-exact compression (from the unreleased 3DO M2) */
|
||||
|
||||
/* for (i=-128;i<128;i++) squares[i+128]=i<0?(-i*i)*2:(i*i)*2; */
|
||||
/* for (i=-128;i<128;i++) { squares[i+128] = i<0?(-i*i)*2:(i*i)*2; } */
|
||||
static int16_t squares[256] = {
|
||||
-32768,-32258,-31752,-31250,-30752,-30258,-29768,-29282,-28800,-28322,-27848,
|
||||
-27378,-26912,-26450,-25992,-25538,-25088,-24642,-24200,-23762,-23328,-22898,
|
||||
-22472,-22050,-21632,-21218,-20808,-20402,-20000,-19602,-19208,-18818,-18432,
|
||||
-18050,-17672,-17298,-16928,-16562,-16200,-15842,-15488,-15138,-14792,-14450,
|
||||
-14112,-13778,-13448,-13122,-12800,-12482,-12168,-11858,-11552,-11250,-10952,
|
||||
-10658,-10368,-10082, -9800, -9522, -9248, -8978, -8712, -8450, -8192, -7938,
|
||||
-7688, -7442, -7200, -6962, -6728, -6498, -6272, -6050, -5832, -5618, -5408,
|
||||
-5202, -5000, -4802, -4608, -4418, -4232, -4050, -3872, -3698, -3528, -3362,
|
||||
-3200, -3042, -2888, -2738, -2592, -2450, -2312, -2178, -2048, -1922, -1800,
|
||||
-1682, -1568, -1458, -1352, -1250, -1152, -1058, -968, -882, -800, -722,
|
||||
-648, -578, -512, -450, -392, -338, -288, -242, -200, -162, -128,
|
||||
-98, -72, -50, -32, -18, -8, -2, 0, 2, 8, 18,
|
||||
32, 50, 72, 98, 128, 162, 200, 242, 288, 338, 392,
|
||||
450, 512, 578, 648, 722, 800, 882, 968, 1058, 1152, 1250,
|
||||
1352, 1458, 1568, 1682, 1800, 1922, 2048, 2178, 2312, 2450, 2592,
|
||||
2738, 2888, 3042, 3200, 3362, 3528, 3698, 3872, 4050, 4232, 4418,
|
||||
4608, 4802, 5000, 5202, 5408, 5618, 5832, 6050, 6272, 6498, 6728,
|
||||
6962, 7200, 7442, 7688, 7938, 8192, 8450, 8712, 8978, 9248, 9522,
|
||||
9800, 10082, 10368, 10658, 10952, 11250, 11552, 11858, 12168, 12482, 12800,
|
||||
13122, 13448, 13778, 14112, 14450, 14792, 15138, 15488, 15842, 16200, 16562,
|
||||
16928, 17298, 17672, 18050, 18432, 18818, 19208, 19602, 20000, 20402, 20808,
|
||||
21218, 21632, 22050, 22472, 22898, 23328, 23762, 24200, 24642, 25088, 25538,
|
||||
25992, 26450, 26912, 27378, 27848, 28322, 28800, 29282, 29768, 30258, 30752,
|
||||
31250, 31752, 32258
|
||||
-32768,-32258,-31752,-31250,-30752,-30258,-29768,-29282,-28800,-28322,-27848,
|
||||
-27378,-26912,-26450,-25992,-25538,-25088,-24642,-24200,-23762,-23328,-22898,
|
||||
-22472,-22050,-21632,-21218,-20808,-20402,-20000,-19602,-19208,-18818,-18432,
|
||||
-18050,-17672,-17298,-16928,-16562,-16200,-15842,-15488,-15138,-14792,-14450,
|
||||
-14112,-13778,-13448,-13122,-12800,-12482,-12168,-11858,-11552,-11250,-10952,
|
||||
-10658,-10368,-10082, -9800, -9522, -9248, -8978, -8712, -8450, -8192, -7938,
|
||||
-7688, -7442, -7200, -6962, -6728, -6498, -6272, -6050, -5832, -5618, -5408,
|
||||
-5202, -5000, -4802, -4608, -4418, -4232, -4050, -3872, -3698, -3528, -3362,
|
||||
-3200, -3042, -2888, -2738, -2592, -2450, -2312, -2178, -2048, -1922, -1800,
|
||||
-1682, -1568, -1458, -1352, -1250, -1152, -1058, -968, -882, -800, -722,
|
||||
-648, -578, -512, -450, -392, -338, -288, -242, -200, -162, -128,
|
||||
-98, -72, -50, -32, -18, -8, -2, 0, 2, 8, 18,
|
||||
32, 50, 72, 98, 128, 162, 200, 242, 288, 338, 392,
|
||||
450, 512, 578, 648, 722, 800, 882, 968, 1058, 1152, 1250,
|
||||
1352, 1458, 1568, 1682, 1800, 1922, 2048, 2178, 2312, 2450, 2592,
|
||||
2738, 2888, 3042, 3200, 3362, 3528, 3698, 3872, 4050, 4232, 4418,
|
||||
4608, 4802, 5000, 5202, 5408, 5618, 5832, 6050, 6272, 6498, 6728,
|
||||
6962, 7200, 7442, 7688, 7938, 8192, 8450, 8712, 8978, 9248, 9522,
|
||||
9800, 10082, 10368, 10658, 10952, 11250, 11552, 11858, 12168, 12482, 12800,
|
||||
13122, 13448, 13778, 14112, 14450, 14792, 15138, 15488, 15842, 16200, 16562,
|
||||
16928, 17298, 17672, 18050, 18432, 18818, 19208, 19602, 20000, 20402, 20808,
|
||||
21218, 21632, 22050, 22472, 22898, 23328, 23762, 24200, 24642, 25088, 25538,
|
||||
25992, 26450, 26912, 27378, 27848, 28322, 28800, 29282, 29768, 30258, 30752,
|
||||
31250, 31752, 32258
|
||||
};
|
||||
|
||||
//for (i=-128;i<128;i++)
|
||||
//{
|
||||
// double j = (i/2)/2.0;
|
||||
// cubes[i+128]=floor(j*j*j);
|
||||
//}
|
||||
static int16_t cubes[256]={
|
||||
-32768,-31256,-31256,-29791,-29791,-28373,-28373,-27000,-27000,-25672,-25672,
|
||||
-24389,-24389,-23149,-23149,-21952,-21952,-20797,-20797,-19683,-19683,-18610,
|
||||
-18610,-17576,-17576,-16581,-16581,-15625,-15625,-14706,-14706,-13824,-13824,
|
||||
-12978,-12978,-12167,-12167,-11391,-11391,-10648,-10648, -9938, -9938, -9261,
|
||||
-9261, -8615, -8615, -8000, -8000, -7415, -7415, -6859, -6859, -6332, -6332,
|
||||
-5832, -5832, -5359, -5359, -4913, -4913, -4492, -4492, -4096, -4096, -3724,
|
||||
-3724, -3375, -3375, -3049, -3049, -2744, -2744, -2460, -2460, -2197, -2197,
|
||||
-1953, -1953, -1728, -1728, -1521, -1521, -1331, -1331, -1158, -1158, -1000,
|
||||
-1000, -857, -857, -729, -729, -614, -614, -512, -512, -422, -422,
|
||||
-343, -343, -275, -275, -216, -216, -166, -166, -125, -125, -91,
|
||||
-91, -64, -64, -43, -43, -27, -27, -16, -16, -8, -8,
|
||||
-3, -3, -1, -1, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 3, 3, 8, 8, 16, 16, 27, 27, 43,
|
||||
43, 64, 64, 91, 91, 125, 125, 166, 166, 216, 216,
|
||||
275, 275, 343, 343, 422, 422, 512, 512, 614, 614, 729,
|
||||
729, 857, 857, 1000, 1000, 1158, 1158, 1331, 1331, 1521, 1521,
|
||||
1728, 1728, 1953, 1953, 2197, 2197, 2460, 2460, 2744, 2744, 3049,
|
||||
3049, 3375, 3375, 3724, 3724, 4096, 4096, 4492, 4492, 4913, 4913,
|
||||
5359, 5359, 5832, 5832, 6332, 6332, 6859, 6859, 7415, 7415, 8000,
|
||||
8000, 8615, 8615, 9261, 9261, 9938, 9938, 10648, 10648, 11391, 11391,
|
||||
12167, 12167, 12978, 12978, 13824, 13824, 14706, 14706, 15625, 15625, 16581,
|
||||
16581, 17576, 17576, 18610, 18610, 19683, 19683, 20797, 20797, 21952, 21952,
|
||||
23149, 23149, 24389, 24389, 25672, 25672, 27000, 27000, 28373, 28373, 29791,
|
||||
29791, 31256, 31256};
|
||||
static void decode_delta_exact(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int16_t * table) {
|
||||
/* for (i=-128;i<128;i++) { double j = (i/2)/2.0; cubes[i+128] = floor(j*j*j); } */
|
||||
static int16_t cubes[256] = {
|
||||
-32768,-31256,-31256,-29791,-29791,-28373,-28373,-27000,-27000,-25672,-25672,
|
||||
-24389,-24389,-23149,-23149,-21952,-21952,-20797,-20797,-19683,-19683,-18610,
|
||||
-18610,-17576,-17576,-16581,-16581,-15625,-15625,-14706,-14706,-13824,-13824,
|
||||
-12978,-12978,-12167,-12167,-11391,-11391,-10648,-10648, -9938, -9938, -9261,
|
||||
-9261, -8615, -8615, -8000, -8000, -7415, -7415, -6859, -6859, -6332, -6332,
|
||||
-5832, -5832, -5359, -5359, -4913, -4913, -4492, -4492, -4096, -4096, -3724,
|
||||
-3724, -3375, -3375, -3049, -3049, -2744, -2744, -2460, -2460, -2197, -2197,
|
||||
-1953, -1953, -1728, -1728, -1521, -1521, -1331, -1331, -1158, -1158, -1000,
|
||||
-1000, -857, -857, -729, -729, -614, -614, -512, -512, -422, -422,
|
||||
-343, -343, -275, -275, -216, -216, -166, -166, -125, -125, -91,
|
||||
-91, -64, -64, -43, -43, -27, -27, -16, -16, -8, -8,
|
||||
-3, -3, -1, -1, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 3, 3, 8, 8, 16, 16, 27, 27, 43,
|
||||
43, 64, 64, 91, 91, 125, 125, 166, 166, 216, 216,
|
||||
275, 275, 343, 343, 422, 422, 512, 512, 614, 614, 729,
|
||||
729, 857, 857, 1000, 1000, 1158, 1158, 1331, 1331, 1521, 1521,
|
||||
1728, 1728, 1953, 1953, 2197, 2197, 2460, 2460, 2744, 2744, 3049,
|
||||
3049, 3375, 3375, 3724, 3724, 4096, 4096, 4492, 4492, 4913, 4913,
|
||||
5359, 5359, 5832, 5832, 6332, 6332, 6859, 6859, 7415, 7415, 8000,
|
||||
8000, 8615, 8615, 9261, 9261, 9938, 9938, 10648, 10648, 11391, 11391,
|
||||
12167, 12167, 12978, 12978, 13824, 13824, 14706, 14706, 15625, 15625, 16581,
|
||||
16581, 17576, 17576, 18610, 18610, 19683, 19683, 20797, 20797, 21952, 21952,
|
||||
23149, 23149, 24389, 24389, 25672, 25672, 27000, 27000, 28373, 28373, 29791,
|
||||
29791, 31256, 31256
|
||||
};
|
||||
|
||||
int32_t hist = stream->adpcm_history1_32;
|
||||
static void decode_delta_exact(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int16_t * table) {
|
||||
int32_t hist = stream->adpcm_history1_32;
|
||||
|
||||
int i;
|
||||
int32_t sample_count;
|
||||
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
int i;
|
||||
int32_t sample_count = 0;
|
||||
|
||||
for (i=first_sample; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
int8_t sample_byte = read_8bit(stream->offset+i,stream->streamfile);
|
||||
int16_t sample;
|
||||
|
||||
if (!(sample_byte & 1)) hist = 0;
|
||||
sample = hist + table[sample_byte+128];
|
||||
|
||||
hist = outbuf[sample_count] = clamp16(sample);
|
||||
}
|
||||
stream->adpcm_history1_32=hist;
|
||||
hist = outbuf[sample_count] = clamp16(sample);
|
||||
}
|
||||
|
||||
stream->adpcm_history1_32 = hist;
|
||||
}
|
||||
|
||||
static void decode_delta_exact_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int16_t * table) {
|
||||
static void decode_delta_exact_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int16_t * table) {
|
||||
int32_t hist = stream->adpcm_history1_32;
|
||||
|
||||
int32_t hist = stream->adpcm_history1_32;
|
||||
int i;
|
||||
int32_t sample_count = 0;
|
||||
|
||||
int i;
|
||||
int32_t sample_count;
|
||||
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
for (i=first_sample; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
int8_t sample_byte = read_8bit(stream->offset+i*channelspacing,stream->streamfile);
|
||||
int16_t sample;
|
||||
|
||||
if (!(sample_byte & 1)) hist = 0;
|
||||
sample = hist + table[sample_byte+128];
|
||||
|
||||
hist = outbuf[sample_count] = clamp16(sample);
|
||||
}
|
||||
stream->adpcm_history1_32=hist;
|
||||
hist = outbuf[sample_count] = clamp16(sample);
|
||||
}
|
||||
|
||||
stream->adpcm_history1_32 = hist;
|
||||
}
|
||||
|
||||
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
decode_delta_exact(stream, outbuf, channelspacing, first_sample, samples_to_do, squares);
|
||||
}
|
||||
|
||||
void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
decode_delta_exact_int(stream, outbuf, channelspacing, first_sample, samples_to_do, squares);
|
||||
}
|
||||
|
||||
void decode_cbd2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
void decode_cbd2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
decode_delta_exact(stream, outbuf, channelspacing, first_sample, samples_to_do, cubes);
|
||||
}
|
||||
|
||||
void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
decode_delta_exact_int(stream, outbuf, channelspacing, first_sample, samples_to_do, cubes);
|
||||
}
|
||||
|
@ -333,6 +333,7 @@ static const char* extension_list[] = {
|
||||
"pona",
|
||||
"pos",
|
||||
"ps2stm", //fake extension for .stm (renamed? to be removed?)
|
||||
"psf",
|
||||
"psh", //fake extension for .vsv (to be removed)
|
||||
"psnd",
|
||||
"psw", //fake extension for .wam (renamed, to be removed)
|
||||
@ -616,6 +617,7 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_PSX, "Playstation 4-bit ADPCM"},
|
||||
{coding_PSX_badflags, "Playstation 4-bit ADPCM (bad flags)"},
|
||||
{coding_PSX_cfg, "Playstation 4-bit ADPCM (configurable)"},
|
||||
{coding_PSX_pivotal, "Playstation 4-bit ADPCM (Pivotal)"},
|
||||
{coding_HEVAG, "Sony HEVAG 4-bit ADPCM"},
|
||||
|
||||
{coding_EA_XA, "Electronic Arts EA-XA 4-bit ADPCM v1"},
|
||||
@ -832,7 +834,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_DSP_WSI, "Alone in the Dark .WSI header"},
|
||||
{meta_AIFC, "Apple AIFF-C (Audio Interchange File Format) header"},
|
||||
{meta_AIFF, "Apple AIFF (Audio Interchange File Format) header"},
|
||||
{meta_STR_SNDS, ".str SNDS SHDR chunk"},
|
||||
{meta_STR_SNDS, "3DO .str header"},
|
||||
{meta_WS_AUD, "Westwood Studios .aud header"},
|
||||
{meta_WS_AUD_old, "Westwood Studios .aud (old) header"},
|
||||
{meta_PS2_IVB, "IVB/BVII header"},
|
||||
@ -881,7 +883,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_SCD_PCM, "Lunar: Eternal Blue .PCM header"},
|
||||
{meta_PS2_PCM, "Konami KCEJ East .PCM header"},
|
||||
{meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV PS2 header"},
|
||||
{meta_PS2_VAS, "Pro Baseball Spirits 5 VAS Header"},
|
||||
{meta_PS2_VAS, "Konami .VAS header"},
|
||||
{meta_PS2_TEC, "assumed TECMO badflagged stream by .tec extension"},
|
||||
{meta_PS2_ENTH, ".enth Header"},
|
||||
{meta_SDT, "High Voltage .sdt header"},
|
||||
@ -904,24 +906,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_PS2_MIHB, "Sony MultiStream MIC header"},
|
||||
{meta_DSP_WII_MUS, "mus header"},
|
||||
{meta_WII_SNG, "SNG DSP Header"},
|
||||
{meta_RSD2VAG, "Radical RSD2/VAG header"},
|
||||
{meta_RSD2PCMB, "Radical RSD2/PCMB header"},
|
||||
{meta_RSD2XADP, "Radical RSD2/XADP header"},
|
||||
{meta_RSD3VAG, "Radical RSD3/VAG header"},
|
||||
{meta_RSD3GADP, "Radical RSD3/GADP header"},
|
||||
{meta_RSD3PCM, "Radical RSD3/PCM header"},
|
||||
{meta_RSD3PCMB, "Radical RSD3/PCMB header"},
|
||||
{meta_RSD4PCMB, "Radical RSD4/PCMB header"},
|
||||
{meta_RSD4PCM, "Radical RSD4/PCM header"},
|
||||
{meta_RSD4RADP, "Radical RSD4/RADP header"},
|
||||
{meta_RSD4VAG, "Radical RSD4/VAG header"},
|
||||
{meta_RSD6XADP, "Radical RSD6/XADP header"},
|
||||
{meta_RSD6VAG, "Radical RSD6/VAG header"},
|
||||
{meta_RSD6WADP, "Radical RSD6/WADP header"},
|
||||
{meta_RSD6RADP, "Radical RSD6/RADP header"},
|
||||
{meta_RSD6XMA, "Radical RSD6/XMA header"},
|
||||
{meta_RSD6AT3P, "Radical RSD6/AT3+ header"},
|
||||
{meta_RSD6WMA, "Radical RSD6/WMA header"},
|
||||
{meta_RSD, "Radical RSD header"},
|
||||
{meta_DC_ASD, "ASD Header"},
|
||||
{meta_NAOMI_SPSD, "Naomi SPSD header"},
|
||||
{meta_FFXI_BGW, "Square Enix .BGW header"},
|
||||
@ -980,7 +965,6 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_PS2_VGV, "Rune: Viking Warlord VGV Header"},
|
||||
{meta_NGC_GCUB, "GCub Header"},
|
||||
{meta_NGC_SCK_DSP, "The Scorpion King SCK Header"},
|
||||
{meta_NGC_SWD, "PSF + Standard DSP Headers"},
|
||||
{meta_CAFF, "Apple Core Audio Format File header"},
|
||||
{meta_PC_MXST, "Lego Island MxSt Header"},
|
||||
{meta_SAB, "Team17 SAB header"},
|
||||
@ -1063,7 +1047,6 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_PS2_HSF, "Lowrider 'HSF' header"},
|
||||
{meta_PS3_IVAG, "PS3 'IVAG' Header"},
|
||||
{meta_PS2_2PFS, "Konami 2PFS header"},
|
||||
{meta_RSD6OOGV, "RSD6/OOGV Header"},
|
||||
{meta_UBI_CKD, "Ubisoft CKD RIFF header"},
|
||||
{meta_PS2_VBK, "PS2 VBK Header"},
|
||||
{meta_OTM, "Otomedius OTM Header"},
|
||||
@ -1205,6 +1188,8 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_SMACKER, "RAD Game Tools SMACKER header"},
|
||||
{meta_MZRT, "id Software MZRT header"},
|
||||
{meta_XAVS, "Reflections XAVS header"},
|
||||
{meta_PSF, "Pivotal PSF header"},
|
||||
{meta_DSP_ITL_i, "Infernal .ITL DSP header"},
|
||||
|
||||
};
|
||||
|
||||
|
@ -8,19 +8,48 @@
|
||||
* Incompatible with decoders that move offsets. */
|
||||
void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
|
||||
int samples_written = 0;
|
||||
int frame_size, samples_per_frame, samples_this_block;
|
||||
int samples_per_frame, samples_this_block; /* used */
|
||||
int samples_per_frame_d = 0, samples_this_block_d = 0; /* default */
|
||||
int samples_per_frame_f = 0, samples_this_block_f = 0; /* first */
|
||||
int samples_per_frame_l = 0, samples_this_block_l = 0; /* last */
|
||||
int has_interleave_first = vgmstream->interleave_first_block_size && vgmstream->channels > 1;
|
||||
int has_interleave_last = vgmstream->interleave_last_block_size && vgmstream->channels > 1;
|
||||
|
||||
frame_size = get_vgmstream_frame_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
|
||||
samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame;
|
||||
|
||||
if (has_interleave_last &&
|
||||
vgmstream->current_sample - vgmstream->samples_into_block + samples_this_block > vgmstream->num_samples) {
|
||||
/* adjust values again if inside last interleave */
|
||||
frame_size = get_vgmstream_shortframe_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream);
|
||||
samples_this_block = vgmstream->interleave_last_block_size / frame_size * samples_per_frame;
|
||||
/* setup */
|
||||
{
|
||||
int frame_size_d = get_vgmstream_frame_size(vgmstream);
|
||||
samples_per_frame_d = get_vgmstream_samples_per_frame(vgmstream);
|
||||
if (frame_size_d == 0 || samples_per_frame_d == 0) goto fail;
|
||||
samples_this_block_d = vgmstream->interleave_block_size / frame_size_d * samples_per_frame_d;
|
||||
}
|
||||
if (has_interleave_first) {
|
||||
int frame_size_f = get_vgmstream_frame_size(vgmstream);
|
||||
samples_per_frame_f = get_vgmstream_samples_per_frame(vgmstream); //todo samples per shortframe
|
||||
if (frame_size_f == 0 || samples_per_frame_f == 0) goto fail;
|
||||
samples_this_block_f = vgmstream->interleave_first_block_size / frame_size_f * samples_per_frame_f;
|
||||
}
|
||||
if (has_interleave_last) {
|
||||
int frame_size_l = get_vgmstream_shortframe_size(vgmstream);
|
||||
samples_per_frame_l = get_vgmstream_samples_per_shortframe(vgmstream);
|
||||
if (frame_size_l == 0 || samples_per_frame_l == 0) goto fail;
|
||||
samples_this_block_l = vgmstream->interleave_last_block_size / frame_size_l * samples_per_frame_l;
|
||||
}
|
||||
|
||||
/* set current values */
|
||||
if (has_interleave_first &&
|
||||
vgmstream->current_sample < samples_this_block_f) {
|
||||
samples_per_frame = samples_per_frame_f;
|
||||
samples_this_block = samples_this_block_f;
|
||||
}
|
||||
else if (has_interleave_last &&
|
||||
vgmstream->current_sample - vgmstream->samples_into_block + samples_this_block_d > vgmstream->num_samples) {
|
||||
samples_per_frame = samples_per_frame_l;
|
||||
samples_this_block = samples_this_block_l;
|
||||
}
|
||||
else {
|
||||
samples_per_frame = samples_per_frame_d;
|
||||
samples_this_block = samples_this_block_d;
|
||||
}
|
||||
|
||||
/* mono interleaved stream with no layout set, just behave like flat layout */
|
||||
@ -28,18 +57,28 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
|
||||
samples_this_block = vgmstream->num_samples;
|
||||
|
||||
|
||||
/* write samples */
|
||||
while (samples_written < sample_count) {
|
||||
int samples_to_do;
|
||||
|
||||
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
|
||||
/* handle looping, restore standard interleave sizes */
|
||||
if (has_interleave_last) { /* assumes that won't loop back into a interleave_last */
|
||||
frame_size = get_vgmstream_frame_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
|
||||
samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame;
|
||||
|
||||
if (has_interleave_first &&
|
||||
vgmstream->current_sample < samples_this_block_f) {
|
||||
/* use first interleave*/
|
||||
samples_per_frame = samples_per_frame_f;
|
||||
samples_this_block = samples_this_block_f;
|
||||
if (samples_this_block == 0 && vgmstream->channels == 1)
|
||||
samples_this_block = vgmstream->num_samples;
|
||||
}
|
||||
else if (has_interleave_last) { /* assumes that won't loop back into a interleave_last */
|
||||
samples_per_frame = samples_per_frame_d;
|
||||
samples_this_block = samples_this_block_d;
|
||||
if (samples_this_block == 0 && vgmstream->channels == 1)
|
||||
samples_this_block = vgmstream->num_samples;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -48,9 +87,7 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
|
||||
samples_to_do = sample_count - samples_written;
|
||||
|
||||
if (samples_to_do == 0) { /* happens when interleave is not set */
|
||||
VGM_LOG("layout_interleave: wrong samples_to_do found\n");
|
||||
memset(buffer + samples_written*vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample_t));
|
||||
break;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer);
|
||||
@ -64,18 +101,34 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
|
||||
if (vgmstream->samples_into_block == samples_this_block) {
|
||||
int ch;
|
||||
|
||||
if (has_interleave_last &&
|
||||
vgmstream->current_sample + samples_this_block > vgmstream->num_samples) {
|
||||
/* adjust values again if inside last interleave */
|
||||
frame_size = get_vgmstream_shortframe_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream);
|
||||
samples_this_block = vgmstream->interleave_last_block_size / frame_size * samples_per_frame;
|
||||
if (has_interleave_first &&
|
||||
vgmstream->current_sample == samples_this_block_f) {
|
||||
/* restore standard frame size after going past first interleave */
|
||||
samples_per_frame = samples_per_frame_d;
|
||||
samples_this_block = samples_this_block_d;
|
||||
if (samples_this_block == 0 && vgmstream->channels == 1)
|
||||
samples_this_block = vgmstream->num_samples;
|
||||
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
off_t skip = vgmstream->interleave_block_size*(vgmstream->channels-ch) +
|
||||
vgmstream->interleave_last_block_size*ch;;
|
||||
off_t skip =
|
||||
vgmstream->interleave_first_skip*(vgmstream->channels-1-ch) +
|
||||
vgmstream->interleave_first_block_size*(vgmstream->channels-ch) +
|
||||
vgmstream->interleave_block_size*ch;
|
||||
vgmstream->ch[ch].offset += skip;
|
||||
}
|
||||
}
|
||||
else if (has_interleave_last &&
|
||||
vgmstream->current_sample + samples_this_block > vgmstream->num_samples) {
|
||||
/* adjust values again if inside last interleave */
|
||||
samples_per_frame = samples_per_frame_l;
|
||||
samples_this_block = samples_this_block_l;
|
||||
if (samples_this_block == 0 && vgmstream->channels == 1)
|
||||
samples_this_block = vgmstream->num_samples;
|
||||
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
off_t skip =
|
||||
vgmstream->interleave_block_size*(vgmstream->channels-ch) +
|
||||
vgmstream->interleave_last_block_size*ch;
|
||||
vgmstream->ch[ch].offset += skip;
|
||||
}
|
||||
}
|
||||
@ -88,6 +141,9 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
|
||||
|
||||
vgmstream->samples_into_block = 0;
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
fail:
|
||||
VGM_LOG("layout_interleave: wrong values found\n");
|
||||
memset(buffer + samples_written*vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample_t));
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "../vgmstream.h"
|
||||
#include "../mixing.h"
|
||||
|
||||
#define VGMSTREAM_MAX_SEGMENTS 255
|
||||
#define VGMSTREAM_MAX_SEGMENTS 512
|
||||
#define VGMSTREAM_SEGMENT_SAMPLE_BUFFER 8192
|
||||
|
||||
|
||||
|
@ -1366,10 +1366,14 @@
|
||||
RelativePath=".\meta\mta2.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ps3_past.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ps3_past.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\psf.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\sgxd.c"
|
||||
>
|
||||
|
@ -195,6 +195,7 @@
|
||||
<ClCompile Include="meta\ps2_wmus.c" />
|
||||
<ClCompile Include="meta\ps3_ivag.c" />
|
||||
<ClCompile Include="meta\ps3_past.c" />
|
||||
<ClCompile Include="meta\psf.c" />
|
||||
<ClCompile Include="meta\sgxd.c" />
|
||||
<ClCompile Include="meta\sk_aud.c" />
|
||||
<ClCompile Include="meta\vawx.c" />
|
||||
|
@ -1369,6 +1369,9 @@
|
||||
<ClCompile Include="meta\ps3_past.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\psf.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\sgxd.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -11,7 +11,8 @@ VGMSTREAM * init_vgmstream_adpcm_capcom(STREAMFILE *streamFile) {
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile,"adpcm"))
|
||||
/* .mca: Monster Hunter Generations Ultimate / XX */
|
||||
if (!check_extensions(streamFile,"adpcm,mca"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x02000000)
|
||||
goto fail;
|
||||
|
@ -31,7 +31,6 @@ VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_idsp_nus3(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_sadb(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_sadf(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_ngc_swd(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_idsp_tt(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_idsp_nl(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_wii_wsd(STREAMFILE *streamFile);
|
||||
@ -51,6 +50,7 @@ VGMSTREAM * init_vgmstream_dsp_itl_ch(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_dsp_adpy(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_dsp_adpx(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_dsp_ds2(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_dsp_itl(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile);
|
||||
|
||||
@ -240,6 +240,7 @@ VGMSTREAM * init_vgmstream_ps2_pcm(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_vas(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_ps2_vas_container(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_tec(STREAMFILE * streamFile);
|
||||
|
||||
@ -302,25 +303,7 @@ VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_wii_mus(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_rsd2vag(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd2pcmb(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd2xadp(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd3pcm(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd3pcmb(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd3gadp(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd3vag(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd4pcmb(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd4pcm(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd4radp(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd4vag(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6vag(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6wadp(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6radp(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE* streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6xma(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6wma(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE * streamFile);
|
||||
|
||||
@ -871,4 +854,7 @@ VGMSTREAM * init_vgmstream_mzrt(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_xavs(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_psf_single(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_psf_segmented(STREAMFILE * streamFile);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
@ -79,6 +79,8 @@ typedef struct {
|
||||
size_t header_spacing; /* distance between DSP header of other channels */
|
||||
off_t start_offset; /* data start */
|
||||
size_t interleave; /* distance between data of other channels */
|
||||
size_t interleave_first; /* same, in the first block */
|
||||
size_t interleave_first_skip; /* extra info */
|
||||
size_t interleave_last; /* same, in the last block */
|
||||
|
||||
meta_t meta_type;
|
||||
@ -208,6 +210,8 @@ static VGMSTREAM * init_vgmstream_dsp_common(STREAMFILE *streamFile, dsp_meta *d
|
||||
if (dspm->interleave == 0 || vgmstream->coding_type == coding_NGC_DSP_subint)
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = dspm->interleave;
|
||||
vgmstream->interleave_first_block_size = dspm->interleave_first;
|
||||
vgmstream->interleave_first_skip = dspm->interleave_first_skip;
|
||||
vgmstream->interleave_last_block_size = dspm->interleave_last;
|
||||
|
||||
{
|
||||
@ -690,33 +694,6 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* SWD - PSF chunks + interleaved dsps [Conflict: Desert Storm 1 & 2] */
|
||||
VGMSTREAM * init_vgmstream_ngc_swd(STREAMFILE *streamFile) {
|
||||
dsp_meta dspm = {0};
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "swd"))
|
||||
goto fail;
|
||||
|
||||
//todo blocked layout when first chunk is 0x50534631 (count + table of 0x0c with offset/sizes)
|
||||
|
||||
if (read_32bitBE(0x00,streamFile) != 0x505346d1) /* PSF\0xd1 */
|
||||
goto fail;
|
||||
|
||||
dspm.channel_count = 2;
|
||||
dspm.max_channels = 2;
|
||||
|
||||
dspm.header_offset = 0x08;
|
||||
dspm.header_spacing = 0x60;
|
||||
dspm.start_offset = dspm.header_offset + 0x60 * dspm.channel_count;
|
||||
dspm.interleave = 0x08;
|
||||
|
||||
dspm.meta_type = meta_NGC_SWD;
|
||||
return init_vgmstream_dsp_common(streamFile, &dspm);
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* IDSP - Traveller's Tales header + interleaved dsps [Lego Batman (Wii), Lego Dimensions (Wii U)] */
|
||||
VGMSTREAM * init_vgmstream_idsp_tt(STREAMFILE *streamFile) {
|
||||
dsp_meta dspm = {0};
|
||||
@ -1278,3 +1255,34 @@ VGMSTREAM * init_vgmstream_dsp_ds2(STREAMFILE *streamFile) {
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* .itl - Incinerator Studios interleaved dsp [Cars Race-o-rama (Wii), MX vs ATV Untamed (Wii)] */
|
||||
VGMSTREAM * init_vgmstream_dsp_itl(STREAMFILE *streamFile) {
|
||||
dsp_meta dspm = {0};
|
||||
size_t stream_size;
|
||||
|
||||
/* checks */
|
||||
/* .itl: standard
|
||||
* .dsp: default to catch a similar file, not sure which devs */
|
||||
if (!check_extensions(streamFile, "itl,dsp"))
|
||||
goto fail;
|
||||
|
||||
stream_size = get_streamfile_size(streamFile);
|
||||
dspm.channel_count = 2;
|
||||
dspm.max_channels = 2;
|
||||
|
||||
dspm.start_offset = 0x60;
|
||||
dspm.interleave = 0x10000;
|
||||
dspm.interleave_first_skip = dspm.start_offset;
|
||||
dspm.interleave_first = dspm.interleave - dspm.interleave_first_skip;
|
||||
dspm.interleave_last = (stream_size / dspm.channel_count) % dspm.interleave;
|
||||
dspm.header_offset = 0x00;
|
||||
dspm.header_spacing = dspm.interleave;
|
||||
|
||||
//todo some files end in half a frame and may click at the very end
|
||||
//todo when .dsp should refer to Ultimate Board Collection (Wii), not sure about dev
|
||||
dspm.meta_type = meta_DSP_ITL_i;
|
||||
return init_vgmstream_dsp_common(streamFile, &dspm);
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -108,12 +108,16 @@ static void kovs_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, v
|
||||
}
|
||||
|
||||
static void psychic_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) {
|
||||
ogg_vorbis_streamfile * const ov_streamfile = datasource;
|
||||
size_t bytes_read = size*nmemb;
|
||||
uint8_t key[6] = { 0x23,0x31,0x20,0x2e,0x2e,0x28 };
|
||||
int i;
|
||||
|
||||
/* bytes add 0x23 ('#') */ //todo incorrect, add changes every 0x64 bytes
|
||||
//todo incorrect, picked value changes (fixed order for all files), or key is bigger
|
||||
/* bytes add key that changes every 0x64 bytes */
|
||||
for (i = 0; i < bytes_read; i++) {
|
||||
((uint8_t*)ptr)[i] += 0x23;
|
||||
int pos = (ov_streamfile->offset + i) / 0x64;
|
||||
((uint8_t*)ptr)[i] += key[pos % sizeof(key)];
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,6 +459,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callb
|
||||
ogg_vorbis_codec_data * data = NULL;
|
||||
OggVorbis_File *ovf = NULL;
|
||||
vorbis_info *vi;
|
||||
char name[STREAM_NAME_SIZE] = {0};
|
||||
|
||||
int loop_flag = ovmi->loop_flag;
|
||||
int32_t loop_start = ovmi->loop_start;
|
||||
@ -626,6 +631,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callb
|
||||
data->disable_reordering = 1;
|
||||
}
|
||||
|
||||
if (strstr(user_comment, "TITLE=") == user_comment) {
|
||||
strncpy(name, user_comment + 6, sizeof(name) - 1);
|
||||
}
|
||||
|
||||
;VGM_LOG("OGG: user_comment=%s\n", user_comment);
|
||||
}
|
||||
}
|
||||
@ -638,9 +647,14 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callb
|
||||
vgmstream->codec_data = data; /* store our fun extra datas */
|
||||
vgmstream->channels = vi->channels;
|
||||
vgmstream->sample_rate = vi->rate;
|
||||
vgmstream->num_streams = ovmi->total_subsongs;
|
||||
vgmstream->stream_size = stream_size;
|
||||
|
||||
if (ovmi->total_subsongs) /* not setting it has some effect when showing stream names */
|
||||
vgmstream->num_streams = ovmi->total_subsongs;
|
||||
|
||||
if (name[0] != '\0')
|
||||
strcpy(vgmstream->stream_name, name);
|
||||
|
||||
vgmstream->num_samples = ov_pcm_total(ovf,-1); /* let libvorbisfile find total samples */
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
|
@ -1,66 +1,122 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* VAS (from Pro Baseball Spirits 5) */
|
||||
|
||||
/* .VAS - from Konami Jikkyou Powerful Pro Yakyuu games */
|
||||
VGMSTREAM * init_vgmstream_ps2_vas(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("vas",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
#if 0
|
||||
if (read_32bitBE(0x00,streamFile) != 0x00000000) /* 0x0 */
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "vas"))
|
||||
goto fail;
|
||||
if (read_32bitLE(0x00,streamFile) + 0x800 != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
loop_flag = (read_32bitLE(0x10,streamFile)!=0);
|
||||
loop_flag = (read_32bitLE(0x10,streamFile) != 0);
|
||||
channel_count = 2;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
start_offset = 0x800;
|
||||
|
||||
/* header is too simple so test a bit */
|
||||
if (!ps_check_format(streamFile, start_offset, 0x1000))
|
||||
goto fail;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = 0x800;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->meta_type = meta_PS2_VAS;
|
||||
vgmstream->sample_rate = read_32bitLE(0x04,streamFile);
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->num_samples = read_32bitLE(0x00,streamFile)*28/16/channel_count;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile)*28/16/channel_count;
|
||||
vgmstream->loop_end_sample = read_32bitLE(0x00,streamFile)*28/16/channel_count;
|
||||
}
|
||||
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x200;
|
||||
vgmstream->meta_type = meta_PS2_VAS;
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
int i;
|
||||
STREAMFILE * file;
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = file;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=start_offset+
|
||||
vgmstream->interleave_block_size*i;
|
||||
|
||||
}
|
||||
}
|
||||
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x00,streamFile), channel_count);
|
||||
vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x14,streamFile), channel_count);
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* .VAS in containers */
|
||||
VGMSTREAM * init_vgmstream_ps2_vas_container(STREAMFILE *streamFile) {
|
||||
VGMSTREAM *vgmstream = NULL;
|
||||
STREAMFILE *temp_streamFile = NULL;
|
||||
off_t subfile_offset = 0;
|
||||
size_t subfile_size = 0;
|
||||
int total_subsongs, target_subsong = streamFile->stream_index;
|
||||
int has_table;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "vas"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00, streamFile) != 0xAB8A5A00) /* fixed value */
|
||||
goto fail;
|
||||
if (read_32bitLE(0x04, streamFile)*0x800 + 0x800 != get_streamfile_size(streamFile)) /* just in case */
|
||||
goto fail;
|
||||
|
||||
/* offset table, 0x98 has table size */
|
||||
has_table = read_32bitLE(0x94, streamFile);
|
||||
|
||||
|
||||
total_subsongs = read_32bitLE(0x08, streamFile); /* also at 0x10 */
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
|
||||
|
||||
|
||||
if (has_table) {
|
||||
off_t header_offset = 0x800 + 0x10*(target_subsong-1);
|
||||
|
||||
/* some values are repeats found in the file sub-header */
|
||||
subfile_offset = read_32bitLE(header_offset + 0x00,streamFile) * 0x800;
|
||||
subfile_size = read_32bitLE(header_offset + 0x08,streamFile) + 0x800;
|
||||
}
|
||||
else {
|
||||
/* a bunch of files */
|
||||
off_t offset = 0x800;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < total_subsongs; i++) {
|
||||
size_t size = read_32bitLE(offset, streamFile) + 0x800;
|
||||
|
||||
if (i + 1 == target_subsong) {
|
||||
subfile_offset = offset;
|
||||
subfile_size = size;
|
||||
break;
|
||||
}
|
||||
|
||||
offset += size;
|
||||
}
|
||||
if (i == total_subsongs)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL);
|
||||
if (!temp_streamFile) goto fail;
|
||||
|
||||
vgmstream = init_vgmstream_ps2_vas(temp_streamFile);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
|
||||
close_streamfile(temp_streamFile);
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_streamFile);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
242
src/meta/psf.c
Normal file
242
src/meta/psf.c
Normal file
@ -0,0 +1,242 @@
|
||||
#include "meta.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
|
||||
/* PSF single - Pivotal games single segment (external in some PC/Xbox or inside bigfiles) [The Great Escape, Conflict series] */
|
||||
VGMSTREAM * init_vgmstream_psf_single(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count, sample_rate, rate_value, interleave;
|
||||
uint32_t psf_config;
|
||||
uint8_t flags;
|
||||
size_t data_size;
|
||||
coding_t codec;
|
||||
|
||||
|
||||
/* checks */
|
||||
/* .psf: actual extension
|
||||
* .swd: bigfile extension */
|
||||
if (!check_extensions(streamFile, "psf,swd"))
|
||||
goto fail;
|
||||
if ((read_32bitBE(0x00,streamFile) & 0xFFFFFF00) != 0x50534600) /* "PSF\00" */
|
||||
goto fail;
|
||||
|
||||
flags = read_8bit(0x03,streamFile);
|
||||
switch(flags) {
|
||||
case 0xC0: /* [The Great Escape (PS2), Conflict: Desert Storm (PS2)] */
|
||||
case 0xA1: /* [Conflict: Desert Storm 2 (PS2)] */
|
||||
case 0x21: /* [Conflict: Desert Storm 2 (PS2), Conflict: Global Storm (PS2)] */
|
||||
//case 0x22: /* [Conflict: Vietman (PS2)] */ //todo weird size value, stereo, only one found
|
||||
channel_count = 2;
|
||||
if (flags == 0x21)
|
||||
channel_count = 1;
|
||||
interleave = 0x10;
|
||||
codec = coding_PSX;
|
||||
start_offset = 0x08;
|
||||
break;
|
||||
|
||||
case 0x80: /* [The Great Escape (PC/Xbox), Conflict: Desert Storm (Xbox/GC), Conflict: Desert Storm 2 (Xbox)] */
|
||||
case 0x81: /* [Conflict: Desert Storm 2 (Xbox), Conflict: Vietnam (Xbox)] */
|
||||
case 0x01: /* [Conflict: Global Storm (Xbox)] */
|
||||
channel_count = 2;
|
||||
if (flags == 0x01)
|
||||
channel_count = 1;
|
||||
interleave = 0x10;
|
||||
codec = coding_PSX_pivotal;
|
||||
start_offset = 0x08;
|
||||
break;
|
||||
|
||||
case 0xD1: /* [Conflict: Desert Storm 2 (GC)] */
|
||||
channel_count = 2;
|
||||
interleave = 0x08;
|
||||
codec = coding_NGC_DSP;
|
||||
start_offset = 0x08 + 0x60 * channel_count;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
loop_flag = 0;
|
||||
|
||||
psf_config = read_32bitLE(0x04, streamFile);
|
||||
|
||||
/* pitch/cents? */
|
||||
rate_value = (psf_config >> 20) & 0xFFF;
|
||||
switch(rate_value) {
|
||||
//case 0xEB5:
|
||||
//case 0xEB4:
|
||||
case 0xEB3: sample_rate = 44100; break;
|
||||
case 0x555: sample_rate = 16000; break;
|
||||
case 0x355: sample_rate = 11050; break;
|
||||
case 0x1d5: sample_rate = 6000; break; /* ? */
|
||||
case 0x1cc: sample_rate = 5000; break;
|
||||
default:
|
||||
VGM_LOG("PSF: unknown rate value %x\n", rate_value);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
data_size = (psf_config & 0xFFFFF) * (interleave * channel_count); /* in blocks */
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_PSF;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
|
||||
switch(codec) {
|
||||
case coding_PSX:
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
|
||||
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
|
||||
break;
|
||||
|
||||
case coding_PSX_pivotal:
|
||||
vgmstream->coding_type = coding_PSX_pivotal;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
|
||||
vgmstream->num_samples = ps_cfg_bytes_to_samples(data_size, 0x10, channel_count);
|
||||
break;
|
||||
|
||||
case coding_NGC_DSP:
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
/* has standard DSP headers at 0x08 */
|
||||
dsp_read_coefs_be(vgmstream,streamFile,0x08+0x1c,0x60);
|
||||
dsp_read_hist_be (vgmstream,streamFile,0x08+0x40,0x60);
|
||||
|
||||
vgmstream->num_samples = read_32bitBE(0x08, streamFile);//dsp_bytes_to_samples(data_size, channel_count);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* PSF segmented - Pivotal games multiple segments (external in some PC/Xbox or inside bigfiles) [The Great Escape, Conflict series] */
|
||||
VGMSTREAM * init_vgmstream_psf_segmented(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
STREAMFILE* temp_streamFile = NULL;
|
||||
segmented_layout_data *data = NULL;
|
||||
int i, segment_count, loop_flag = 0, loop_start = 0, loop_end = 0;
|
||||
off_t offset;
|
||||
|
||||
|
||||
/* checks */
|
||||
/* .psf: actual extension
|
||||
* .swd: bigfile extension */
|
||||
if (!check_extensions(streamFile, "psf,swd"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00,streamFile) != 0x50534660 && /* "PSF\60" [The Great Escape (PC/Xbox/PS2), Conflict: Desert Storm (Xbox/GC)] */
|
||||
read_32bitBE(0x00,streamFile) != 0x50534631) /* "PSF\31" [Conflict: Desert Storm 2 (Xbox/GC/PS2)] */
|
||||
goto fail;
|
||||
|
||||
segment_count = read_32bitLE(0x04, streamFile);
|
||||
loop_flag = 0;
|
||||
|
||||
offset = 0x08;
|
||||
offset += 0x0c; /* first segment points to itself? */
|
||||
segment_count--;
|
||||
|
||||
/* build segments */
|
||||
data = init_layout_segmented(segment_count);
|
||||
if (!data) goto fail;
|
||||
|
||||
for (i = 0; i < segment_count; i++) {
|
||||
off_t psf_offset;
|
||||
size_t psf_size;
|
||||
uint32_t psf_id;
|
||||
|
||||
/* mini table */
|
||||
psf_offset = read_32bitLE(offset + 0x00, streamFile);
|
||||
/* 0x04-0c: 0x02*4 transition segments (possibly to 4 song variations) */
|
||||
|
||||
/* use last section transition as loop */
|
||||
if (i + 1 == segment_count) {
|
||||
loop_flag = 1;
|
||||
loop_start = read_16bitLE(offset + 0x0a, streamFile) - 1; /* also ignore first segment */
|
||||
loop_end = i;
|
||||
}
|
||||
|
||||
/* multiple segment can point to the same PSF offset (for repeated song sections) */
|
||||
//todo reuse repeated VGMSTREAMs to improve memory a bit
|
||||
|
||||
psf_id = read_32bitBE(psf_offset + 0x00, streamFile);
|
||||
psf_size = read_32bitLE(psf_offset + 0x04, streamFile);
|
||||
if (psf_id == 0x505346D1) //todo improve
|
||||
psf_size = (psf_size & 0xFFFFF) * 0x10;
|
||||
else
|
||||
psf_size = (psf_size & 0xFFFFF) * 0x20;
|
||||
//;VGM_LOG("PSF: offset=%lx, size=%x\n", psf_offset, psf_size);
|
||||
|
||||
temp_streamFile = setup_subfile_streamfile(streamFile, psf_offset, psf_size, "psf");
|
||||
if (!temp_streamFile) goto fail;
|
||||
|
||||
data->segments[i] = init_vgmstream_psf_single(temp_streamFile);
|
||||
if (!data->segments[i]) goto fail;
|
||||
|
||||
offset += 0x0c;
|
||||
}
|
||||
|
||||
/* setup VGMSTREAMs */
|
||||
if (!setup_layout_segmented(data))
|
||||
goto fail;
|
||||
vgmstream = allocate_segmented_vgmstream(data,loop_flag, loop_start, loop_end);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->stream_size = get_streamfile_size(streamFile);
|
||||
|
||||
return vgmstream;
|
||||
fail:
|
||||
if (!vgmstream) free_layout_segmented(data);
|
||||
close_streamfile(temp_streamFile);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
VGMSTREAM * init_vgmstream_sch(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "sch"))
|
||||
goto fail;
|
||||
|
||||
/* chunked format (id+size, GC pads to 0x20 and uses BE/inverted ids):
|
||||
* - SCH\0: start
|
||||
* - IMUS: points to a external .psf + segment table (same as in .psf, TGE only?)
|
||||
* - BANK: volume/etc info? points to something?
|
||||
* - PFSM: single .psf-like file (larger header)
|
||||
* - PFST: points to single PSF offset (.psf in TGE, or STREAMS.SWD); may be chained to next PFST?
|
||||
*
|
||||
* no other info so total subsongs would be count of usable chunks
|
||||
* in later games, segmented .psf seems to be removed and PFST is used instead
|
||||
*/
|
||||
|
||||
return vgmstream;
|
||||
fail:
|
||||
if (!vgmstream) free_layout_layered(data);
|
||||
close_streamfile(temp_streamFile);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
1368
src/meta/rsd.c
1368
src/meta/rsd.c
File diff suppressed because it is too large
Load Diff
@ -67,11 +67,14 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x2000;
|
||||
vgmstream->interleave_first_skip = 0x60;
|
||||
vgmstream->interleave_first_block_size = vgmstream->interleave_block_size - vgmstream->interleave_first_skip;
|
||||
|
||||
/* standard dsp header at start_offset */
|
||||
dsp_read_coefs_be(vgmstream, streamFile, start_offset+0x1c, vgmstream->interleave_block_size);
|
||||
dsp_read_hist_be(vgmstream, streamFile, start_offset+0x40, vgmstream->interleave_block_size);
|
||||
//todo first_interleave: 0x2000 - 60
|
||||
|
||||
start_offset += vgmstream->interleave_first_skip;
|
||||
break;
|
||||
|
||||
case 0x70635F00: /* "pc_\0" */
|
||||
|
@ -1,118 +1,98 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* 3DO format, .str extension and possibly a CTRL header, blocks and
|
||||
* AIFF-C style format specifier. Blocks are not IFF-compliant. Interesting
|
||||
* blocks are all SNDS
|
||||
*/
|
||||
|
||||
/* .str - 3DO format with CTRL/SNDS/SHDR blocks [Icebreaker (3DO), Battle Pinball (3DO)] */
|
||||
VGMSTREAM * init_vgmstream_str_snds(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset, shdr_offset = -1;
|
||||
int loop_flag, channel_count, found_shdr = 0;
|
||||
size_t file_size, ctrl_size = -1;
|
||||
|
||||
int channel_count;
|
||||
int loop_flag = 0;
|
||||
off_t SHDR_offset = -1;
|
||||
int FoundSHDR = 0;
|
||||
int CTRL_size = -1;
|
||||
|
||||
size_t file_size;
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "str"))
|
||||
goto fail;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("str",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check for opening CTRL or SNDS chunk */
|
||||
if (read_32bitBE(0x0,streamFile) != 0x4354524c && /* CTRL */
|
||||
read_32bitBE(0x0,streamFile) != 0x534e4453 && // SNDS
|
||||
read_32bitBE(0x0,streamFile) != 0x53484452) // SHDR
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4354524c && /* "CTRL" */
|
||||
read_32bitBE(0x00,streamFile) != 0x534e4453 && /* "SNDS" */
|
||||
read_32bitBE(0x00,streamFile) != 0x53484452) /* "SHDR" */
|
||||
goto fail;
|
||||
|
||||
file_size = get_streamfile_size(streamFile);
|
||||
start_offset = 0x00;
|
||||
|
||||
/* scan chunks until we find a SNDS containing a SHDR */
|
||||
{
|
||||
off_t current_chunk;
|
||||
off_t current_chunk = 0;
|
||||
|
||||
current_chunk = 0;
|
||||
|
||||
while (!FoundSHDR && current_chunk < file_size) {
|
||||
while (!found_shdr && current_chunk < file_size) {
|
||||
if (current_chunk < 0) goto fail;
|
||||
|
||||
if (current_chunk+read_32bitBE(current_chunk+4,streamFile) >=
|
||||
file_size) goto fail;
|
||||
if (current_chunk+read_32bitBE(current_chunk+0x04,streamFile) >= file_size)
|
||||
goto fail;
|
||||
|
||||
switch (read_32bitBE(current_chunk,streamFile))
|
||||
{
|
||||
case 0x4354524C: /* CTRL */
|
||||
/* to distinguish between styles */
|
||||
CTRL_size = read_32bitBE(current_chunk+4,streamFile);
|
||||
break;
|
||||
case 0x534e4453: /* SNDS */
|
||||
switch (read_32bitBE(current_chunk+16,streamFile))
|
||||
{
|
||||
case 0x53484452: /* SHDR */
|
||||
FoundSHDR = 1;
|
||||
SHDR_offset = current_chunk+16;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
switch (read_32bitBE(current_chunk,streamFile)) {
|
||||
case 0x4354524C: /* "CTRL" */
|
||||
ctrl_size = read_32bitBE(current_chunk+4,streamFile);
|
||||
break;
|
||||
|
||||
case 0x534e4453: /* "SNDS" */
|
||||
switch (read_32bitBE(current_chunk+16,streamFile)) {
|
||||
case 0x53484452: /* SHDR */
|
||||
found_shdr = 1;
|
||||
shdr_offset = current_chunk+16;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x53484452: /* SHDR */
|
||||
switch (read_32bitBE(current_chunk+0x7C, streamFile))
|
||||
{
|
||||
case 0x4354524C: /* CTRL */
|
||||
// to distinguish between styles
|
||||
CTRL_size = read_32bitBE(current_chunk + 0x80, streamFile);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0x53484452: /* "SHDR" */
|
||||
switch (read_32bitBE(current_chunk+0x7C, streamFile)) {
|
||||
case 0x4354524C: /* "CTRL" */
|
||||
/* to distinguish between styles */
|
||||
ctrl_size = read_32bitBE(current_chunk + 0x80, streamFile);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ignore others for now */
|
||||
break;
|
||||
}
|
||||
|
||||
current_chunk += read_32bitBE(current_chunk+4,streamFile);
|
||||
current_chunk += read_32bitBE(current_chunk+0x04,streamFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (!FoundSHDR) goto fail;
|
||||
if (!found_shdr) goto fail;
|
||||
|
||||
/* details */
|
||||
channel_count = read_32bitBE(SHDR_offset+0x20,streamFile);
|
||||
channel_count = read_32bitBE(shdr_offset+0x20,streamFile);
|
||||
loop_flag = 0;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
if ((CTRL_size == 0x1C) ||
|
||||
(CTRL_size == 0x0B) ||
|
||||
(CTRL_size == -1))
|
||||
{
|
||||
vgmstream->num_samples =
|
||||
read_32bitBE(SHDR_offset+0x2c,streamFile)-1; /* sample count? */
|
||||
vgmstream->meta_type = meta_STR_SNDS;
|
||||
vgmstream->sample_rate = read_32bitBE(shdr_offset+0x1c,streamFile);
|
||||
|
||||
if (ctrl_size == 0x1C || ctrl_size == 0x0B || ctrl_size == -1) {
|
||||
vgmstream->num_samples = read_32bitBE(shdr_offset+0x2c,streamFile) - 1; /* sample count? */
|
||||
}
|
||||
else {
|
||||
vgmstream->num_samples =
|
||||
read_32bitBE(SHDR_offset+0x2c,streamFile) /* frame count? */
|
||||
* 0x10;
|
||||
else {
|
||||
vgmstream->num_samples = read_32bitBE(shdr_offset+0x2c,streamFile) * 0x10; /* frame count? */
|
||||
}
|
||||
vgmstream->num_samples /= vgmstream->channels;
|
||||
|
||||
vgmstream->num_samples/=vgmstream->channels;
|
||||
|
||||
vgmstream->sample_rate = read_32bitBE(SHDR_offset+0x1c,streamFile);
|
||||
switch (read_32bitBE(SHDR_offset+0x24,streamFile)) {
|
||||
case 0x53445832: /* SDX2 */
|
||||
switch (read_32bitBE(shdr_offset+0x24,streamFile)) {
|
||||
case 0x53445832: /* "SDX2" */
|
||||
if (channel_count > 1) {
|
||||
vgmstream->coding_type = coding_SDX2_int;
|
||||
vgmstream->interleave_block_size = 1;
|
||||
@ -123,33 +103,12 @@ VGMSTREAM * init_vgmstream_str_snds(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
}
|
||||
vgmstream->layout_type = layout_blocked_str_snds;
|
||||
vgmstream->meta_type = meta_STR_SNDS;
|
||||
|
||||
/* channels and loop flag are set by allocate_vgmstream */
|
||||
if (loop_flag) {
|
||||
/* just guessin', no way to set loop flag anyway */
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
}
|
||||
|
||||
/* open the file for reading by each channel */
|
||||
{
|
||||
int i;
|
||||
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
|
||||
STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!vgmstream->ch[0].streamfile) goto fail;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
|
||||
}
|
||||
}
|
||||
|
||||
/* start me up */
|
||||
block_update_str_snds(0,vgmstream);
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
size_t file_size, channel_size, interleave;
|
||||
size_t file_size, channel_size, interleave, interleave_first = 0, interleave_first_skip = 0;
|
||||
meta_t meta_type;
|
||||
int channel_count = 0, loop_flag, sample_rate;
|
||||
uint32_t vag_id, version;
|
||||
@ -80,7 +80,7 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
|
||||
|
||||
case 0x70474156: /* pGAV (little endian / stereo) [Jak 3 (PS2), Jak X (PS2)] */
|
||||
meta_type = meta_PS2_pGAV;
|
||||
start_offset = 0x00; //todo 0x30, requires interleave_first
|
||||
start_offset = 0x30;
|
||||
|
||||
if (read_32bitBE(0x20,streamFile) == 0x53746572) { /* "Ster" */
|
||||
channel_count = 2;
|
||||
@ -91,7 +91,8 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
|
||||
interleave = 0x1000; /* Jak X interleave, includes header */
|
||||
else
|
||||
interleave = 0x2000; /* Jak 3 interleave in rare files, no header */
|
||||
//todo interleave_first = interleave - start_offset; /* interleave includes header */
|
||||
interleave_first = interleave - start_offset; /* interleave includes header */
|
||||
interleave_first_skip = start_offset;
|
||||
}
|
||||
else {
|
||||
channel_count = 1;
|
||||
@ -127,21 +128,21 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
|
||||
}
|
||||
else if (read_32bitBE(0x6000,streamFile) == 0x56414770) { /* "VAGp" */
|
||||
/* The Simpsons Wrestling (PS1) */
|
||||
start_offset = 0x00; //todo 0x30, requires interleave_first
|
||||
start_offset = 0x30;
|
||||
channel_count = 2;
|
||||
interleave = 0x6000;
|
||||
//todo interleave_first = interleave - start_offset; /* includes header */
|
||||
channel_size += 0x30;
|
||||
interleave_first = interleave - start_offset; /* includes header */
|
||||
interleave_first_skip = start_offset;
|
||||
|
||||
loop_flag = 0;
|
||||
}
|
||||
else if (read_32bitBE(0x1000,streamFile) == 0x56414770) { /* "VAGp" */
|
||||
/* Shikigami no Shiro (PS2) */
|
||||
start_offset = 0x00; //todo 0x30, requires interleave_first
|
||||
start_offset = 0x30;
|
||||
channel_count = 2;
|
||||
interleave = 0x1000;
|
||||
//todo interleave_first = interleave - start_offset; /* includes header */
|
||||
channel_size += 0x30;
|
||||
interleave_first = interleave - start_offset; /* includes header */
|
||||
interleave_first_skip = start_offset;
|
||||
|
||||
loop_flag = ps_find_loop_offsets(streamFile, start_offset, channel_size*channel_count, channel_count, interleave, &loop_start_sample, &loop_end_sample);
|
||||
}
|
||||
@ -244,6 +245,9 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
|
||||
vgmstream->coding_type = coding_HEVAG;
|
||||
vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->interleave_first_block_size = interleave_first;
|
||||
vgmstream->interleave_first_skip = interleave_first_skip;
|
||||
|
||||
|
||||
read_string(vgmstream->stream_name,0x10+1, 0x20,streamFile); /* always, can be null */
|
||||
|
||||
|
@ -221,6 +221,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
start_offset = ww.data_offset;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
@ -303,7 +304,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
cfg.setup_type = WWV_EXTERNAL_CODEBOOKS; /* setup_type will be corrected later */
|
||||
break;
|
||||
|
||||
case 0x2a: /* uncommon (mid 2011) [inFamous 2 (PS3)] */
|
||||
case 0x2a: /* uncommon (mid 2011) [inFamous 2 (PS3), Captain America: Super Soldier (X360)] */
|
||||
data_offsets = 0x10;
|
||||
block_offsets = 0x28;
|
||||
cfg.header_type = WWV_TYPE_2;
|
||||
@ -325,6 +326,14 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
}
|
||||
ww.data_size -= audio_offset;
|
||||
|
||||
|
||||
/* detect normal packets */
|
||||
if (vorb_size == 0x2a) {
|
||||
/* almost all blocksizes are 0x08+0x0B except a few with 0x0a+0x0a [Captain America: Super Soldier (X360) voices/sfx] */
|
||||
if (cfg.blocksize_0_exp == cfg.blocksize_1_exp)
|
||||
cfg.packet_type = WWV_STANDARD;
|
||||
}
|
||||
|
||||
/* detect setup type:
|
||||
* - full inline: ~2009, ex. The King of Fighters XII (X360), The Saboteur (PC)
|
||||
* - trimmed inline: ~2010, ex. Army of Two: 40 days (X360) some multiplayer files
|
||||
@ -378,11 +387,9 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
cfg.blocksize_0_exp = read_8bit(extra_offset + block_offsets + 0x01, streamFile); /* big */
|
||||
ww.data_size -= audio_offset;
|
||||
|
||||
/* Normal packets are used rarely (ex. Oddworld New 'n' Tasty! (PSV)). They are hard to detect (decoding
|
||||
* will mostly work with garbage results) but we'll try. Setup size and "fmt" bitrate fields may matter too. */
|
||||
/* detect normal packets */
|
||||
if (ww.extra_size == 0x30) {
|
||||
/* all blocksizes I've seen are 0x08+0x0B except Oddworld (PSV), that uses 0x09+0x09
|
||||
* (maybe lower spec machines = needs simpler packets) */
|
||||
/* almost all blocksizes are 0x08+0x0B except some with 0x09+0x09 [Oddworld New 'n' Tasty! (PSV)] */
|
||||
if (cfg.blocksize_0_exp == cfg.blocksize_1_exp)
|
||||
cfg.packet_type = WWV_STANDARD;
|
||||
}
|
||||
@ -438,6 +445,15 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* for some reason all(?) DSP .wem do full loops (even mono/jingles/etc) but
|
||||
* several tracks do loop like this, so disable it for short-ish tracks */
|
||||
if (ww.loop_flag && vgmstream->loop_start_sample == 0 &&
|
||||
vgmstream->loop_end_sample < 20*ww.sample_rate) { /* in seconds */
|
||||
vgmstream->loop_flag = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* get coefs and default history */
|
||||
dsp_read_coefs(vgmstream,streamFile,wiih_offset, 0x2e, ww.big_endian);
|
||||
for (i=0; i < ww.channels; i++) {
|
||||
|
@ -635,10 +635,11 @@ static int get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_head
|
||||
}
|
||||
|
||||
//;VGM_LOG("XSB: name found=%i at %lx\n", xsb.parse_found, xsb.name_offset);
|
||||
if (!xsb.parse_found || xsb.name_offset == 0)
|
||||
if (!xsb.name_len || xsb.name[0] == '\0')
|
||||
goto fail;
|
||||
|
||||
read_string(buf,maxsize, xsb.name_offset,streamFile); /* null-terminated */
|
||||
strncpy(buf,xsb.name,maxsize);
|
||||
buf[maxsize-1] = '\0';
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#ifndef _XWB_XSB_H_
|
||||
#define _XWB_XSB_H_
|
||||
#include "meta.h"
|
||||
|
||||
#define XSB_XACT1_0_MAX 5 /* Unreal Championship (Xbox) */
|
||||
#define XSB_XACT1_1_MAX 8 /* Die Hard: Vendetta (Xbox) */
|
||||
@ -30,9 +31,9 @@ typedef struct {
|
||||
off_t cue_names_offset;
|
||||
|
||||
/* output */
|
||||
int parse_found;
|
||||
int parse_done;
|
||||
off_t name_offset;
|
||||
char name[STREAM_NAME_SIZE];
|
||||
int name_len;
|
||||
|
||||
} xsb_header;
|
||||
|
||||
@ -41,24 +42,30 @@ static void xsb_check_stream(xsb_header * xsb, int stream_index, int wavebank_in
|
||||
if (xsb->parse_done)
|
||||
return;
|
||||
|
||||
/* multiple names may correspond to a stream, so commenting parse_done
|
||||
* will allow to search for other names instead of first only */
|
||||
/* multiple names may correspond to a stream (ex. Blue Dragon), so we concat all */
|
||||
if (xsb->selected_stream == stream_index &&
|
||||
(xsb->selected_wavebank == wavebank_index || wavebank_index == -1 || wavebank_index == 255)) {
|
||||
xsb->name_offset = name_offset;
|
||||
xsb->parse_found = 1;
|
||||
xsb->parse_done = 1;
|
||||
char name[STREAM_NAME_SIZE];
|
||||
size_t name_size;
|
||||
|
||||
name_size = read_string(name,sizeof(name), name_offset,sf); /* null-terminated */
|
||||
|
||||
if (xsb->name_len) {
|
||||
const char *cat = "; ";
|
||||
int cat_len = 2;
|
||||
|
||||
if (xsb->name_len + cat_len + name_size + 1 < STREAM_NAME_SIZE) {
|
||||
strcat(xsb->name + xsb->name_len, cat);
|
||||
strcat(xsb->name + xsb->name_len, name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strcpy(xsb->name, name);
|
||||
}
|
||||
xsb->name_len += name_size;
|
||||
//xsb->parse_done = 1; /* uncomment this to stop reading after first name */
|
||||
//;VGM_LOG("XSB: parse found stream=%i, wavebank=%i, name_offset=%lx\n", stream_index, wavebank_index, name_offset);
|
||||
}
|
||||
|
||||
#if 0 // for debugging purposes
|
||||
{
|
||||
char stream_name[255];
|
||||
read_string(stream_name,255, name_offset,sf); /* null-terminated */
|
||||
;VGM_LOG("XSB: stream=%i, wavebank=%i, name=%lx=%s vs s=%i, w=%i\n", stream_index, wavebank_index, name_offset, stream_name, xsb->selected_stream, xsb->selected_wavebank);
|
||||
xsb->parse_done = 0; /* keep parsing */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* old XACT1 is a bit different and much of it is unknown but this seems to work.
|
||||
|
@ -118,12 +118,12 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_ps2_pcm,
|
||||
init_vgmstream_ps2_rkv,
|
||||
init_vgmstream_ps2_vas,
|
||||
init_vgmstream_ps2_vas_container,
|
||||
init_vgmstream_ps2_tec,
|
||||
init_vgmstream_ps2_enth,
|
||||
init_vgmstream_sdt,
|
||||
init_vgmstream_aix,
|
||||
init_vgmstream_ngc_tydsp,
|
||||
init_vgmstream_ngc_swd,
|
||||
init_vgmstream_capdsp,
|
||||
init_vgmstream_xbox_wvs,
|
||||
init_vgmstream_ngc_wvs,
|
||||
@ -157,21 +157,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_wii_mus,
|
||||
init_vgmstream_dc_asd,
|
||||
init_vgmstream_naomi_spsd,
|
||||
init_vgmstream_rsd2vag,
|
||||
init_vgmstream_rsd2pcmb,
|
||||
init_vgmstream_rsd2xadp,
|
||||
init_vgmstream_rsd3vag,
|
||||
init_vgmstream_rsd3gadp,
|
||||
init_vgmstream_rsd3pcm,
|
||||
init_vgmstream_rsd3pcmb,
|
||||
init_vgmstream_rsd4pcmb,
|
||||
init_vgmstream_rsd4pcm,
|
||||
init_vgmstream_rsd4radp,
|
||||
init_vgmstream_rsd4vag,
|
||||
init_vgmstream_rsd6vag,
|
||||
init_vgmstream_rsd6wadp,
|
||||
init_vgmstream_rsd6xadp,
|
||||
init_vgmstream_rsd6radp,
|
||||
init_vgmstream_rsd,
|
||||
init_vgmstream_bgw,
|
||||
init_vgmstream_spw,
|
||||
init_vgmstream_ps2_ass,
|
||||
@ -305,7 +291,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_ps3_ivag,
|
||||
init_vgmstream_ps2_2pfs,
|
||||
init_vgmstream_xnb,
|
||||
init_vgmstream_rsd6oogv,
|
||||
init_vgmstream_ubi_ckd,
|
||||
init_vgmstream_ps2_vbk,
|
||||
init_vgmstream_otm,
|
||||
@ -335,7 +320,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_ogl,
|
||||
init_vgmstream_mc3,
|
||||
init_vgmstream_gtd,
|
||||
init_vgmstream_rsd6xma,
|
||||
init_vgmstream_ta_aac_x360,
|
||||
init_vgmstream_ta_aac_ps3,
|
||||
init_vgmstream_ta_aac_mobile,
|
||||
@ -395,8 +379,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_waf,
|
||||
init_vgmstream_wave,
|
||||
init_vgmstream_wave_segmented,
|
||||
init_vgmstream_rsd6at3p,
|
||||
init_vgmstream_rsd6wma,
|
||||
init_vgmstream_smv,
|
||||
init_vgmstream_nxap,
|
||||
init_vgmstream_ea_wve_au00,
|
||||
@ -486,6 +468,9 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_smk,
|
||||
init_vgmstream_mzrt,
|
||||
init_vgmstream_xavs,
|
||||
init_vgmstream_psf_single,
|
||||
init_vgmstream_psf_segmented,
|
||||
init_vgmstream_dsp_itl,
|
||||
|
||||
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
|
||||
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
|
||||
@ -1190,7 +1175,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
case coding_HEVAG:
|
||||
return 28;
|
||||
case coding_PSX_cfg:
|
||||
return (vgmstream->interleave_block_size - 1) * 2; /* decodes 1 byte into 2 bytes */
|
||||
case coding_PSX_pivotal:
|
||||
return (vgmstream->interleave_block_size - 0x01) * 2; /* size 0x01 header */
|
||||
|
||||
case coding_EA_XA:
|
||||
case coding_EA_XA_int:
|
||||
@ -1378,6 +1364,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
case coding_HEVAG:
|
||||
return 0x10;
|
||||
case coding_PSX_cfg:
|
||||
case coding_PSX_pivotal:
|
||||
return vgmstream->interleave_block_size;
|
||||
|
||||
case coding_EA_XA:
|
||||
@ -1693,6 +1680,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, vgmstream->interleave_block_size);
|
||||
}
|
||||
break;
|
||||
case coding_PSX_pivotal:
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
decode_psx_pivotal(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
|
||||
vgmstream->channels,vgmstream->samples_into_block,samples_to_do,
|
||||
vgmstream->interleave_block_size);
|
||||
}
|
||||
break;
|
||||
case coding_HEVAG:
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
decode_hevag(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
|
||||
@ -2429,6 +2423,11 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
||||
snprintf(temp,TEMPSIZE, "interleave: %#x bytes\n", (int32_t)vgmstream->interleave_block_size);
|
||||
concatn(length,desc,temp);
|
||||
|
||||
if (vgmstream->interleave_first_block_size) {
|
||||
snprintf(temp,TEMPSIZE, "interleave first block: %#x bytes\n", (int32_t)vgmstream->interleave_first_block_size);
|
||||
concatn(length,desc,temp);
|
||||
}
|
||||
|
||||
if (vgmstream->interleave_last_block_size) {
|
||||
snprintf(temp,TEMPSIZE, "interleave last block: %#x bytes\n", (int32_t)vgmstream->interleave_last_block_size);
|
||||
concatn(length,desc,temp);
|
||||
@ -2824,6 +2823,12 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s
|
||||
vgmstream->coding_type == coding_CRI_HCA)
|
||||
return 1;
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
/* stream/offsets not needed, managed by decoder */
|
||||
if (vgmstream->coding_type == coding_OGG_VORBIS)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
/* stream/offsets not needed, managed by decoder */
|
||||
if (vgmstream->coding_type == coding_FFmpeg)
|
||||
|
@ -104,7 +104,8 @@ typedef enum {
|
||||
coding_XA, /* CD-ROM XA */
|
||||
coding_PSX, /* Sony PS ADPCM (VAG) */
|
||||
coding_PSX_badflags, /* Sony PS ADPCM with custom flag byte */
|
||||
coding_PSX_cfg, /* Sony PS ADPCM with configurable frame size (FF XI, SGXD type 5, Bizarre Creations) */
|
||||
coding_PSX_cfg, /* Sony PS ADPCM with configurable frame size (int math) */
|
||||
coding_PSX_pivotal, /* Sony PS ADPCM with configurable frame size (float math) */
|
||||
coding_HEVAG, /* Sony PSVita ADPCM */
|
||||
|
||||
coding_EA_XA, /* Electronic Arts EA-XA ADPCM v1 (stereo) aka "EA ADPCM" */
|
||||
@ -389,7 +390,6 @@ typedef enum {
|
||||
meta_PS2_ENTH, /* Enthusia */
|
||||
meta_SDT, /* Baldur's Gate - Dark Alliance */
|
||||
meta_NGC_TYDSP, /* Ty - The Tasmanian Tiger */
|
||||
meta_NGC_SWD, /* Conflict - Desert Storm 1 & 2 */
|
||||
meta_CAPDSP, /* Capcom DSP Header [no header_id] */
|
||||
meta_DC_STR, /* SEGA Stream Asset Builder */
|
||||
meta_DC_STR_V2, /* variant of SEGA Stream Asset Builder */
|
||||
@ -420,27 +420,7 @@ typedef enum {
|
||||
meta_NGC_PDT, /* Mario Party 6 */
|
||||
meta_DC_ASD, /* Miss Moonligh */
|
||||
meta_NAOMI_SPSD, /* Guilty Gear X */
|
||||
|
||||
meta_RSD2VAG, /* RSD2VAG */
|
||||
meta_RSD2PCMB, /* RSD2PCMB */
|
||||
meta_RSD2XADP, /* RSD2XADP */
|
||||
meta_RSD3VAG, /* RSD3VAG */
|
||||
meta_RSD3GADP, /* RSD3GADP */
|
||||
meta_RSD3PCM, /* RSD3PCM */
|
||||
meta_RSD3PCMB, /* RSD3PCMB */
|
||||
meta_RSD4PCMB, /* RSD4PCMB */
|
||||
meta_RSD4PCM, /* RSD4PCM */
|
||||
meta_RSD4RADP, /* RSD4RADP */
|
||||
meta_RSD4VAG, /* RSD4VAG */
|
||||
meta_RSD6VAG, /* RSD6VAG */
|
||||
meta_RSD6WADP, /* RSD6WADP */
|
||||
meta_RSD6XADP, /* RSD6XADP */
|
||||
meta_RSD6RADP, /* RSD6RADP */
|
||||
meta_RSD6OOGV, /* RSD6OOGV */
|
||||
meta_RSD6XMA, /* RSD6XMA */
|
||||
meta_RSD6AT3P, /* RSD6AT3+ */
|
||||
meta_RSD6WMA, /* RSD6WMA */
|
||||
|
||||
meta_RSD,
|
||||
meta_PS2_ASS, /* ASS */
|
||||
meta_SEG, /* Eragon */
|
||||
meta_NDS_STRM_FFTA2, /* Final Fantasy Tactics A2 */
|
||||
@ -732,6 +712,8 @@ typedef enum {
|
||||
meta_SMACKER,
|
||||
meta_MZRT,
|
||||
meta_XAVS,
|
||||
meta_PSF,
|
||||
meta_DSP_ITL_i,
|
||||
|
||||
} meta_t;
|
||||
|
||||
@ -843,6 +825,8 @@ typedef struct {
|
||||
|
||||
/* layouts/block config */
|
||||
size_t interleave_block_size; /* interleave, or block/frame size (depending on the codec) */
|
||||
size_t interleave_first_block_size; /* different interleave for first block */
|
||||
size_t interleave_first_skip; /* data skipped before interleave first (needed to skip other channels) */
|
||||
size_t interleave_last_block_size; /* smaller interleave for last block */
|
||||
|
||||
/* subsong config */
|
||||
|
Loading…
Reference in New Issue
Block a user