Add .pdt subsongs [Cubic Lode Runner (GC), Muscle Champion (GC)]

This commit is contained in:
bnnm 2018-04-01 02:15:10 +02:00
parent effe65c934
commit 9db9ae563a
3 changed files with 148 additions and 0 deletions

View File

@ -286,6 +286,7 @@ VGMSTREAM * init_vgmstream_psx_fag(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ngc_pdt_split(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_wii_mus(STREAMFILE * streamFile);

View File

@ -1,6 +1,152 @@
#include "meta.h"
#include "../coding/coding.h"
/* PDT - Hudson's stream container [Adventure Island (GC), Muscle Champion (GC), Mario Party series (GC)] */
VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
int loop_flag, channel_count, sample_rate;
size_t entries, nibble_size, loop_start;
off_t entries_offset, coefs_offset, header_offset;
off_t channel1_offset = 0, channel2_offset = 0, coef_offset = 0;
int total_subsongs, target_subsong = streamFile->stream_index;
/* checks */
if (!check_extensions(streamFile, "pdt"))
goto fail;
if (read_16bitBE(0x00,streamFile) != 0x01) /* version? */
goto fail;
if (read_32bitBE(0x04,streamFile) != 0x04) /* entry size? */
goto fail;
if (read_32bitBE(0x08,streamFile) != 0x7d00) /* not-sample rate? */
goto fail;
if (read_32bitBE(0x0c,streamFile) != 0x02 && /* not-channels? */
read_32bitBE(0x0c,streamFile) != 0x04)
goto fail;
//VGM_LOG("1\n");
entries = read_16bitBE(0x02,streamFile);
entries_offset = read_32bitBE(0x10,streamFile);
coefs_offset = read_32bitBE(0x14,streamFile);
//headers_offset = read_32bitBE(0x18,streamFile); /* we'll have pointers to those two */
//streams_offset = read_32bitBE(0x1c,streamFile);
/* find subsongs and target header, as entries can be empty/repeated */
{
/* tables to cache reads as it can be kinda slow with so many loops */
uint32_t data_offsets[0x2000];
uint32_t entry_offset, data_offset;
int i,j;
if (entries > 0x2000)
goto fail;
total_subsongs = 0;
if (target_subsong == 0) target_subsong = 1;
header_offset = 0;
for (i = 0; i < entries; i++) {
int is_unique = 1;
entry_offset = read_32bitBE(entries_offset + i*0x04,streamFile);
if (entry_offset == 0x00)
continue;
data_offset = read_32bitBE(entry_offset+0x10,streamFile);
/* check if current entry header was repeated (same file offset, difference in flags only) */
for (j = 0; j < total_subsongs; j++) {
if (data_offsets[j] == data_offset) {
is_unique = 0;
break;
}
}
if (!is_unique)
continue;
data_offsets[total_subsongs] = data_offset;
total_subsongs++;
/* target GET, but keep going to count subsongs */
if (!header_offset && target_subsong == total_subsongs) {
header_offset = entry_offset;
}
}
}
//VGM_LOG("header: %lx\n", header_offset);//todo
/* parse header */
{
uint8_t flags;
size_t coef1_entry;
off_t coef1_offset;
flags = read_8bit(header_offset+0x00,streamFile);
sample_rate = read_32bitBE(header_offset+0x04,streamFile);
/* 0x01: unknown + 0x4000 */
sample_rate = read_32bitBE(header_offset+0x04,streamFile);
nibble_size = read_32bitBE(header_offset+0x08,streamFile);
loop_start = read_32bitBE(header_offset+0x0c,streamFile);
channel1_offset = read_32bitBE(header_offset+0x10,streamFile);
coef1_entry = read_16bitBE(header_offset+0x14,streamFile);
coef1_offset = coefs_offset + coef1_entry*0x20;
if (flags & 0x01) {
//size_t coef2_entry;
//off_t coef2_offset;
channel2_offset = read_32bitBE(header_offset+0x18,streamFile);
/* always after coef1 in practice */
//coef2_entry = read_16bitBE(header_offset+0x1c,streamFile);
//coef2_offset = coefs_offset + coef2_entry*0x20;
//if (coef1_offset + 0x20 != coef2_offset)
// goto fail;
}
coef_offset = coef1_offset;
loop_flag = (flags & 0x02);
channel_count = (flags & 0x01) ? 2 : 1;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
//vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count);//todo remove
vgmstream->num_samples = dsp_nibbles_to_samples(nibble_size);
//vgmstream->loop_start_sample = dsp_bytes_to_samples(loop_start, channel_count);//todo remove
vgmstream->loop_start_sample = dsp_nibbles_to_samples(loop_start);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->meta_type = meta_NGC_PDT;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_none;
dsp_read_coefs_be(vgmstream, streamFile, coef_offset, 0x20);
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = nibble_size / 2 * channel_count;
if (!vgmstream_open_stream(vgmstream,streamFile,channel1_offset))
goto fail;
/* channels may start at slightly separated offsets */
if (channel_count == 2) {
vgmstream->ch[1].channel_start_offset =
vgmstream->ch[1].offset = channel2_offset;
}
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
/* PDT - custom fake header for split (PDTExt) .ptd [Mario Party (GC)] */
VGMSTREAM * init_vgmstream_ngc_pdt_split(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;

View File

@ -156,6 +156,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_psx_fag,
init_vgmstream_ps2_mihb,
init_vgmstream_ngc_pdt_split,
init_vgmstream_ngc_pdt,
init_vgmstream_wii_mus,
init_vgmstream_dc_asd,
init_vgmstream_naomi_spsd,