diff --git a/src/base/decode.c b/src/base/decode.c index f5feaa3d..f55c3275 100644 --- a/src/base/decode.c +++ b/src/base/decode.c @@ -449,7 +449,7 @@ int decode_get_samples_per_frame(VGMSTREAM* vgmstream) { return 28; case coding_PSX_cfg: case coding_PSX_pivotal: - return (vgmstream->interleave_block_size - 0x01) * 2; /* size 0x01 header */ + return (vgmstream->frame_size - 0x01) * 2; /* size 0x01 header */ case coding_EA_XA: case coding_EA_XA_int: @@ -669,7 +669,7 @@ int decode_get_frame_size(VGMSTREAM* vgmstream) { return 0x10; case coding_PSX_cfg: case coding_PSX_pivotal: - return vgmstream->interleave_block_size; + return vgmstream->frame_size; case coding_EA_XA: return 0x1E; @@ -998,14 +998,14 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ for (ch = 0; ch < vgmstream->channels; ch++) { decode_psx_configurable(&vgmstream->ch[ch], buffer+ch, vgmstream->channels, vgmstream->samples_into_block, samples_to_do, - vgmstream->interleave_block_size, vgmstream->codec_config); + vgmstream->frame_size, vgmstream->codec_config); } break; case coding_PSX_pivotal: for (ch = 0; ch < vgmstream->channels; ch++) { decode_psx_pivotal(&vgmstream->ch[ch], buffer+ch, vgmstream->channels, vgmstream->samples_into_block, samples_to_do, - vgmstream->interleave_block_size); + vgmstream->frame_size); } break; case coding_HEVAG: diff --git a/src/meta/lsf.c b/src/meta/lsf.c index 94f7741d..f1446e7a 100644 --- a/src/meta/lsf.c +++ b/src/meta/lsf.c @@ -1,43 +1,85 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* .lsf - from Atod games [Fastlane Street Racing (iPhone), Chicane Street Racing prototype (Gizmondo)] */ -VGMSTREAM * init_vgmstream_lsf_n1nj4n(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - size_t file_size; +/* .lsf - from Gizmondo Studios Helsingborg/Atod AB games [Chicane Street Racing (Gizmondo), Fastlane Street Racing (iOS)] */ +VGMSTREAM* init_vgmstream_lsf_n1nj4n(STREAMFILE *sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset, data_size, loop_start = 0, loop_end = 0; + int channels, loop_flag, sample_rate; + bool is_v2 = false; /* checks */ - if (!check_extensions(streamFile, "lsf")) + if ((read_u64be(0x00, sf) & 0xFFFFFFFFFFFFFF00) == get_id64be("!n1nj4n\0")) + is_v2 = false; + else if ((read_u64be(0x00, sf) & 0xFFFFFFFFFFFFFF00) == get_id64be("n1nj4n!\0")) + is_v2 = true; /* some files in Agaju: The Sacred Path (Gizmondo) */ + else + return NULL; + + /* .lsf: actual extension, exe strings seem to call this format "LSF" as well */ + if (!check_extensions(sf, "lsf")) + return NULL; + + uint8_t flags = read_u8(0x07, sf); + uint32_t offset = 0x08; + + if (flags & 0x01) { + loop_start = read_u32le(offset + 0x00,sf); + loop_end = read_u32le(offset + 0x04,sf); + offset += 0x08; + } + + if ((flags & 0x01) && (flags & 0x02)) { + //00: loop hist related? + offset += 0x04; + } + + if (flags & 0x02) { + int count = read_u32le(offset + 0x00,sf); /* not channels */ + // per entry: + // 00: channel related? + // 04: null? + // 0c: ~0x3130? + offset += 0x04 + 0x0c * count; + } + + sample_rate = read_u32le(offset + 0x00, sf); + data_size = read_u32le(offset + 0x04, sf); + offset += 0x08; + start_offset = offset; + + if (start_offset + data_size != get_streamfile_size(sf)) goto fail; - if (read_32bitBE(0x00, streamFile) != 0x216E316E || // "!n1n" - read_32bitBE(0x04, streamFile) != 0x6A346E00) // "j4n\0" - goto fail; - - file_size = get_streamfile_size(streamFile); - if (read_32bitLE(0x0C, streamFile) + 0x10 != file_size) - goto fail; - - loop_flag = 0; - channel_count = 1; - start_offset = 0x10; - + channels = 1; + loop_flag = loop_end > 0; /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; vgmstream->meta_type = meta_LSF_N1NJ4N; - vgmstream->sample_rate = read_32bitLE(0x08, streamFile); - vgmstream->num_samples = (file_size-0x10)/0x1c*0x1b*2; - vgmstream->coding_type = coding_LSF; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x1c; + vgmstream->sample_rate = sample_rate; - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + if (is_v2) { + vgmstream->coding_type = coding_PSX_cfg; + vgmstream->layout_type = layout_none; + vgmstream->frame_size = 0x10; + } + else { + /* custom codec but basically obfuscted PSX-cfg */ + vgmstream->coding_type = coding_LSF; + vgmstream->layout_type = layout_interleave; //TODO: flat but decoder doesn't handle it + vgmstream->interleave_block_size = 0x1c; + vgmstream->frame_size = 0x1c; /* fixed but used below */ + } + + vgmstream->num_samples = ps_cfg_bytes_to_samples(data_size, vgmstream->frame_size, channels); + vgmstream->loop_start_sample = ps_cfg_bytes_to_samples(loop_start, vgmstream->frame_size, channels); + vgmstream->loop_end_sample = ps_cfg_bytes_to_samples(loop_end, vgmstream->frame_size, channels); + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) goto fail; return vgmstream; diff --git a/src/vgmstream.c b/src/vgmstream.c index f864a90b..958120af 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -1149,13 +1149,6 @@ int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_o return 1; #endif - if ((vgmstream->coding_type == coding_PSX_cfg || - vgmstream->coding_type == coding_PSX_pivotal) && - (vgmstream->interleave_block_size == 0 || vgmstream->interleave_block_size > 0x50)) { - VGM_LOG("VGMSTREAM: PSX-cfg decoder with wrong frame size %x\n", vgmstream->interleave_block_size); - goto fail; - } - if ((vgmstream->coding_type == coding_CRI_ADX || vgmstream->coding_type == coding_CRI_ADX_enc_8 || vgmstream->coding_type == coding_CRI_ADX_enc_9 || @@ -1168,16 +1161,24 @@ int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_o if ((vgmstream->coding_type == coding_MSADPCM || vgmstream->coding_type == coding_MSADPCM_ck || vgmstream->coding_type == coding_MSADPCM_int || - vgmstream->coding_type == coding_MS_IMA || vgmstream->coding_type == coding_MS_IMA_mono + vgmstream->coding_type == coding_MS_IMA || vgmstream->coding_type == coding_MS_IMA_mono || + vgmstream->coding_type == coding_PSX_cfg || vgmstream->coding_type == coding_PSX_pivotal ) && vgmstream->frame_size == 0) { vgmstream->frame_size = vgmstream->interleave_block_size; } + if ((vgmstream->coding_type == coding_PSX_cfg || + vgmstream->coding_type == coding_PSX_pivotal) && + (vgmstream->frame_size == 0 || vgmstream->frame_size > 0x50)) { + VGM_LOG("VGMSTREAM: PSX-cfg decoder with wrong frame size %x\n", vgmstream->frame_size); + goto fail; + } + if ((vgmstream->coding_type == coding_MSADPCM || vgmstream->coding_type == coding_MSADPCM_ck || vgmstream->coding_type == coding_MSADPCM_int) && - (vgmstream->frame_size > MSADPCM_MAX_BLOCK_SIZE)) { + (vgmstream->frame_size == 0 || vgmstream->frame_size > MSADPCM_MAX_BLOCK_SIZE)) { VGM_LOG("VGMSTREAM: MSADPCM decoder with wrong frame size %x\n", vgmstream->frame_size); goto fail; }