Fix some .str+wav [Zapper Beta (PS2)]

This commit is contained in:
bnnm 2023-10-14 19:49:17 +02:00
parent 5928c8df0d
commit 28f9781a89
7 changed files with 104 additions and 14 deletions

View File

@ -155,6 +155,7 @@
<ClInclude Include="meta\sfh_streamfile.h" />
<ClInclude Include="meta\sqex_streamfile.h" />
<ClInclude Include="meta\sscf_encrypted.h" />
<ClInclude Include="meta\str_wav_streamfile.h" />
<ClInclude Include="meta\txth_streamfile.h" />
<ClInclude Include="meta\ubi_bao_streamfile.h" />
<ClInclude Include="meta\ubi_ckd_cwav_streamfile.h" />

View File

@ -290,6 +290,9 @@
<ClInclude Include="meta\sscf_encrypted.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\str_wav_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\txth_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>

View File

@ -1,9 +1,10 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/layout_utils.h"
#include "str_wav_streamfile.h"
typedef enum { PSX, DSP, XBOX, WMA, IMA, XMA2, MPEG } strwav_codec;
typedef enum { PSX, PSX_chunked, DSP, XBOX, WMA, IMA, XMA2, MPEG } strwav_codec;
typedef struct {
int tracks;
int channels;
@ -104,6 +105,29 @@ VGMSTREAM* init_vgmstream_str_wav(STREAMFILE* sf) {
vgmstream->interleave_block_size = strwav.interleave;
break;
case PSX_chunked: { /* hack */
//tracks are stereo blocks of size 0x20000 * tracks, containing 4 interleaves of 0x8000:
// | 1 2 1 2 | 3 4 3 4 | 5 6 5 6 | 1 2 1 2 | 3 4 3 4 | 5 6 5 6 | ...
vgmstream->coding_type = coding_PSX;
vgmstream->interleave_block_size = strwav.interleave;
for (int i = 0; i < strwav.tracks; i++) {
uint32_t chunk_size = 0x20000;
int layer_channels = 2;
STREAMFILE* temp_sf = setup_str_wav_streamfile(sf, 0x00, strwav.tracks, i, chunk_size);
if (!temp_sf) goto fail;
bool res = layered_add_sf(vgmstream, strwav.tracks, layer_channels, temp_sf);
close_streamfile(temp_sf);
if (!res)
goto fail;
}
if (!layered_add_done(vgmstream))
goto fail;
break;
}
case DSP:
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
@ -456,8 +480,8 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa
strwav->codec = PSX;
strwav->interleave = strwav->tracks > 1 ? 0x8000 : 0x8000;
//todo: tracks are stereo blocks of size 0x20000*tracks, containing 4 interleaves of 0x8000:
// | 1 2 1 2 | 3 4 3 4 | 5 6 5 6 | 1 2 1 2 | 3 4 3 4 | 5 6 5 6 | ...
if (strwav->tracks > 1) /* hack */
strwav->codec = PSX_chunked;
;VGM_LOG("STR+WAV: header ZPb (PS2)\n");
return 1;
}
@ -690,7 +714,7 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa
/* 0x4c: ? (some low number) */
strwav->tracks = read_u8 (0x4e,sf_h);
/* 0x4f: 16 bps */
/* 0x54: channels per each track? (ex. 2 stereo track: 0x02,0x02) */
/* 0x54: channels per each track (ex. 2 stereo track: 0x02,0x02) */
/* 0x64: channels */
/* 0x70+: tables */
@ -772,8 +796,14 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa
strwav->channels = read_s32be(0x70,sf_h);
/* possible flags/ch numbers at 0x4A/61 */
/* other possibly-useful flags (see Karaoke Wii too):
* - 0x4b: number of tracks
* - 0x60: channels per track, ex. 020202 = 3 tracks of 2ch (max 0x08 = 8)
* - 0xa0: sizes per track (max 0x20 = 8)
* - 0xc0: samples per track (max 0x20 = 8)
* - rest: info/seek table? */
if (read_s32be(0x78,sf_h) != 0) { /* KRev */
strwav->tracks = strwav->channels / 2;
strwav->num_samples = strwav->loop_end; /* num_samples here seems to be data size */
strwav->interleave = read_s32be(0xA0,sf_h); /* one size per file, but CBR = same for all */

View File

@ -0,0 +1,21 @@
#ifndef _STR_WAV_STREAMFILE_H_
#define _STR_WAV_STREAMFILE_H_
#include "deblock_streamfile.h"
/* Deblocks streams */
static STREAMFILE* setup_str_wav_streamfile(STREAMFILE* sf, off_t stream_start, int stream_count, int stream_number, size_t interleave) {
STREAMFILE *new_sf = NULL;
deblock_config_t cfg = {0};
cfg.stream_start = stream_start;
cfg.chunk_size = interleave;
cfg.step_start = stream_number;
cfg.step_count = stream_count;
/* setup sf */
new_sf = open_wrap_streamfile(sf);
new_sf = open_io_deblock_streamfile_f(new_sf, &cfg);
return new_sf;
}
#endif

View File

@ -56,11 +56,11 @@ fail:
}
bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) {
static bool layered_add_internal(VGMSTREAM* vs, int layers, int layer_channels, STREAMFILE* sf) {
int i;
layered_layout_data* data;
if (!vs || !vs->codec_data) {
if (!vs) {
goto fail;
}
@ -99,9 +99,12 @@ bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) {
data->layers[i]->loop_end_sample = vs->loop_end_sample;
data->layers[i]->codec_data = vs->codec_data;
if (!data->layers[i]->codec_data) goto fail;
data->layers[i]->coding_type = vs->coding_type;
data->layers[i]->layout_type = layout_none;
data->layers[i]->interleave_block_size = vs->interleave_block_size;
if (vs->interleave_block_size)
data->layers[i]->layout_type = layout_interleave;
vs->codec_data = NULL; /* moved to layer, don't hold it */
@ -112,6 +115,18 @@ fail:
return false;
}
bool layered_add_sf(VGMSTREAM* vs, int layers, int layer_channels, STREAMFILE* sf) {
return layered_add_internal(vs, layers, layer_channels, sf);
}
bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) {
if (!vs->codec_data)
return false;
return layered_add_internal(vs, layers, layer_channels, NULL);
}
bool layered_add_done(VGMSTREAM* vs) {
//TODO: some extra checks/setup?

View File

@ -8,6 +8,10 @@ typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*);
/* add a new layer from subfile (setups layout if needed) */
bool layered_add_subfile(VGMSTREAM* vs, int layers, int layer_channels, STREAMFILE* sf, uint32_t offset, uint32_t size, const char* ext, init_vgmstream_t init_vgmstream);
/* add a new layer from base vgmstream (setups layout if needed) */
bool layered_add_sf(VGMSTREAM* vs, int layers, int layer_channels, STREAMFILE* sf);
/* add a new layer from codec data (setups layout if needed)
* codec is passed in the vs for easier free/etc control */
bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels);

View File

@ -616,12 +616,6 @@ static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) {
try_dual_file_stereo(vgmstream, sf, init_vgmstream_function);
}
/* clean as loops are readable metadata but loop fields may contain garbage
* (done *after* dual stereo as it needs loop fields to match) */
if (!vgmstream->loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = 0;
}
#ifdef VGM_USE_FFMPEG
/* check FFmpeg streams here, for lack of a better place */
@ -678,6 +672,28 @@ static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) {
void setup_vgmstream(VGMSTREAM* vgmstream) {
//TODO improve cleanup (done here to handle manually added layers)
/* sanify loops and remove bad metadata (some layouts will behave incorrectly) */
if (vgmstream->loop_flag) {
if (vgmstream->loop_end_sample <= vgmstream->loop_start_sample
|| vgmstream->loop_end_sample > vgmstream->num_samples
|| vgmstream->loop_start_sample < 0) {
VGM_LOG("VGMSTREAM: wrong loops ignored (lss=%i, lse=%i, ns=%i)\n",
vgmstream->loop_start_sample, vgmstream->loop_end_sample, vgmstream->num_samples);
vgmstream->loop_flag = 0;
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = 0;
}
}
/* clean as loops are readable metadata but loop fields may contain garbage
* (done *after* dual stereo as it needs loop fields to match) */
if (!vgmstream->loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = 0;
}
/* save start things so we can restart when seeking */
memcpy(vgmstream->start_ch, vgmstream->ch, sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
memcpy(vgmstream->start_vgmstream, vgmstream, sizeof(VGMSTREAM));