mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-19 00:04:04 +01:00
Fix some Ogg .wav [Kirara Kirara NTR (PC)]
This commit is contained in:
parent
112aab1923
commit
5adae4db4c
@ -215,7 +215,13 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk
|
||||
break;
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case 0x6771: /* Ogg Vorbis (mode 3+) */
|
||||
//case 0x674f: /* Ogg Vorbis (mode 1) */
|
||||
//case 0x6750: /* Ogg Vorbis (mode 2) */
|
||||
//case 0x6751: /* Ogg Vorbis (mode 3) */
|
||||
case 0x676f: /* Ogg Vorbis (mode 1+) [Only One 2 (PC)] */
|
||||
//case 0x6770: /* Ogg Vorbis (mode 2+) */
|
||||
case 0x6771: /* Ogg Vorbis (mode 3+) [Liar-soft games] */
|
||||
/* vorbis.acm codecs (official-ish, "+" = CBR-style modes?) */
|
||||
fmt->coding_type = coding_OGG_VORBIS;
|
||||
break;
|
||||
#endif
|
||||
@ -233,7 +239,7 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk
|
||||
(read_u16 (offset+0x26,sf));
|
||||
uint32_t guid3 = read_u32be(offset+0x28,sf);
|
||||
uint32_t guid4 = read_u32be(offset+0x2c,sf);
|
||||
//;VGM_LOG("RIFF: guid %08x %08x %08x %08x\n", guid1, guid2, guid3, guid4);
|
||||
//;VGM_LOG("riff: guid %08x %08x %08x %08x\n", guid1, guid2, guid3, guid4);
|
||||
|
||||
/* PCM GUID (0x00000001,0000,0010,80,00,00,AA,00,38,9B,71) */
|
||||
if (guid1 == 0x00000001 && guid2 == 0x00000010 && guid3 == 0x800000AA && guid4 == 0x00389B71) {
|
||||
@ -280,7 +286,7 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk
|
||||
|
||||
default:
|
||||
/* FFmpeg may play it */
|
||||
//vgm_logi("WWISE: unknown codec 0x%04x (report)\n", fmt->format);
|
||||
//vgm_logi("RIFF: unknown codec 0x%04x (report)\n", fmt->format);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -318,7 +324,10 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
||||
off_t mwv_ctrl_offset = -1;
|
||||
|
||||
|
||||
/* check extension */
|
||||
/* checks*/
|
||||
if (!is_id32be(0x00,sf,"RIFF"))
|
||||
goto fail;
|
||||
|
||||
/* .lwav: to avoid hijacking .wav
|
||||
* .xwav: fake for Xbox games (not needed anymore)
|
||||
* .da: The Great Battle VI (PS1)
|
||||
@ -355,21 +364,19 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* check header */
|
||||
if (!is_id32be(0x00,sf,"RIFF"))
|
||||
goto fail;
|
||||
riff_size = read_u32le(0x04,sf);
|
||||
|
||||
if (!is_id32be(0x08,sf, "WAVE"))
|
||||
goto fail;
|
||||
|
||||
riff_size = read_u32le(0x04,sf);
|
||||
file_size = get_streamfile_size(sf);
|
||||
|
||||
/* some games have wonky sizes, selectively fix to catch bad rips and new mutations */
|
||||
if (file_size != riff_size + 0x08) {
|
||||
uint16_t codec = read_u16le(0x14,sf);
|
||||
|
||||
if (codec == 0x6771 && riff_size + 0x08 + 0x01 == file_size)
|
||||
riff_size += 0x01; /* [Shikkoku no Sharnoth (PC)] (Sony Sound Forge?) */
|
||||
if ((codec & 0xFF00) == 0x6700 && riff_size + 0x08 + 0x01 == file_size)
|
||||
riff_size += 0x01; /* [Shikkoku no Sharnoth (PC), Only One 2 (PC)] (Sony Sound Forge?) */
|
||||
|
||||
else if (codec == 0x0069 && riff_size == file_size)
|
||||
riff_size -= 0x08; /* [Dynasty Warriors 3 (Xbox), BloodRayne (Xbox)] */
|
||||
@ -422,6 +429,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
||||
/* check for truncated RIFF */
|
||||
if (file_size != riff_size + 0x08) {
|
||||
vgm_logi("RIFF: wrong expected size (report/re-rip?)\n");
|
||||
VGM_LOG("riff: file_size = %x, riff_size+8 = %x\n", file_size, riff_size + 0x08); /* don't log to user */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -774,8 +782,9 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
||||
#endif
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case coding_OGG_VORBIS: {
|
||||
/* special handling of Liar-soft's buggy RIFF+Ogg made with Soundforge [Shikkoku no Sharnoth (PC)] */
|
||||
STREAMFILE *temp_sf = setup_riff_ogg_streamfile(sf, start_offset, data_size);
|
||||
/* special handling of Liar-soft's buggy RIFF+Ogg made with Soundforge/vorbis.acm [Shikkoku no Sharnoth (PC)],
|
||||
* and rarely other devs, not always buggy [Kirara Kirara NTR (PC), No One 2 (PC)] */
|
||||
STREAMFILE* temp_sf = setup_riff_ogg_streamfile(sf, start_offset, data_size);
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
vgmstream->codec_data = init_ogg_vorbis(temp_sf, 0x00, get_streamfile_size(temp_sf), NULL);
|
||||
@ -983,13 +992,13 @@ VGMSTREAM* init_vgmstream_rifx(STREAMFILE* sf) {
|
||||
int FormatChunkFound = 0, DataChunkFound = 0;
|
||||
|
||||
|
||||
/* check extension, case insensitive */
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "RIFX"))
|
||||
goto fail;
|
||||
|
||||
if (!check_extensions(sf, "wav,lwav"))
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if (!is_id32be(0x00,sf, "RIFX"))
|
||||
goto fail;
|
||||
if (!is_id32be(0x08,sf, "WAVE"))
|
||||
goto fail;
|
||||
|
||||
|
@ -3,22 +3,22 @@
|
||||
#include "deblock_streamfile.h"
|
||||
|
||||
typedef struct {
|
||||
off_t patch_offset;
|
||||
uint32_t patch_offset;
|
||||
} riff_ogg_io_data;
|
||||
|
||||
static size_t riff_ogg_io_read(STREAMFILE *sf, uint8_t *dest, off_t offset, size_t length, riff_ogg_io_data* data) {
|
||||
size_t bytes = read_streamfile(dest, offset, length, sf);
|
||||
static size_t riff_ogg_io_read(STREAMFILE* sf, uint8_t* dst, uint32_t offset, size_t length, riff_ogg_io_data* data) {
|
||||
size_t bytes = read_streamfile(dst, offset, length, sf);
|
||||
|
||||
/* has garbage init Oggs pages, patch bad flag */
|
||||
if (data->patch_offset && data->patch_offset >= offset && data->patch_offset < offset + bytes) {
|
||||
VGM_ASSERT(dest[data->patch_offset - offset] != 0x02, "RIFF Ogg: bad patch offset at %lx\n", data->patch_offset);
|
||||
dest[data->patch_offset - offset] = 0x00;
|
||||
VGM_ASSERT(dst[data->patch_offset - offset] != 0x02, "RIFF Ogg: bad patch offset at %x\n", data->patch_offset);
|
||||
dst[data->patch_offset - offset] = 0x00;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static size_t ogg_get_page(uint8_t *buf, size_t bufsize, off_t offset, STREAMFILE *sf) {
|
||||
static size_t ogg_get_page(uint8_t* buf, size_t bufsize, uint32_t offset, STREAMFILE* sf) {
|
||||
size_t segments, bytes, page_size;
|
||||
int i;
|
||||
|
||||
@ -43,8 +43,8 @@ fail:
|
||||
}
|
||||
|
||||
/* patches Ogg with weirdness */
|
||||
static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE *sf, off_t start, size_t size) {
|
||||
off_t patch_offset = 0;
|
||||
static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE* sf, uint32_t start, size_t size) {
|
||||
uint32_t patch_offset = 0;
|
||||
size_t real_size = size;
|
||||
uint8_t buf[0x1000];
|
||||
|
||||
@ -52,11 +52,11 @@ static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE *sf, off_t start, size_t
|
||||
/* initial page flag is repeated and causes glitches in decoders, find bad offset */
|
||||
//todo callback could patch on-the-fly by analyzing all "OggS", but is problematic due to arbitrary offsets
|
||||
{
|
||||
off_t offset = start;
|
||||
uint32_t offset = start;
|
||||
size_t page_size;
|
||||
off_t offset_limit = start + size; /* usually in the first 0x3000 but can be +0x100000 */
|
||||
uint32_t offset_limit = start + size; /* usually in the first 0x3000 but can be +0x100000 */
|
||||
//todo this doesn't seem to help much
|
||||
STREAMFILE *temp_sf = reopen_streamfile(sf, 0x100); /* use small-ish sf to avoid reading the whole thing */
|
||||
STREAMFILE* temp_sf = reopen_streamfile(sf, 0x100); /* use small-ish sf to avoid reading the whole thing */
|
||||
|
||||
/* first page is ok */
|
||||
page_size = ogg_get_page(buf, sizeof(buf), offset, temp_sf);
|
||||
@ -66,7 +66,7 @@ static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE *sf, off_t start, size_t
|
||||
page_size = ogg_get_page(buf, sizeof(buf), offset, temp_sf);
|
||||
if (page_size == 0) break;
|
||||
|
||||
if (get_u32be(buf + 0x00) != 0x4f676753) /* "OggS" */
|
||||
if (get_u32be(buf + 0x00) != get_id32be("OggS"))
|
||||
break;
|
||||
|
||||
if (get_u16be(buf + 0x04) == 0x0002) { /* start page flag */
|
||||
@ -80,8 +80,9 @@ static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE *sf, off_t start, size_t
|
||||
|
||||
close_streamfile(temp_sf);
|
||||
|
||||
if (patch_offset == 0)
|
||||
return NULL;
|
||||
/* no need to patch initial flag */
|
||||
//if (patch_offset == 0)
|
||||
// return NULL;
|
||||
}
|
||||
|
||||
/* has a bunch of padding(?) pages at the end with no data nor flag that confuse decoders, find actual end */
|
||||
@ -89,14 +90,14 @@ static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE *sf, off_t start, size_t
|
||||
size_t chunk_size = sizeof(buf); /* not worth testing more */
|
||||
size_t max_size = size;
|
||||
size_t pos;
|
||||
off_t read_offset = start + size - chunk_size;
|
||||
uint32_t read_offset = start + size - chunk_size;
|
||||
|
||||
pos = read_streamfile(buf, read_offset, chunk_size, sf);
|
||||
if (read_offset < 0 || pos <= 0x1a) return NULL;
|
||||
|
||||
pos -= 0x1a; /* at least one OggS page */
|
||||
while (pos > 0) {
|
||||
if (get_u32be(buf + pos + 0x00) == 0x4f676753) { /* "OggS" */
|
||||
if (get_u32be(buf + pos + 0x00) == get_id32be("OggS")) {
|
||||
|
||||
if (get_u16be(buf + pos + 0x04) == 0x0004) { /* last page flag is ok */
|
||||
real_size = max_size;
|
||||
@ -112,7 +113,7 @@ static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE *sf, off_t start, size_t
|
||||
|
||||
/* actual custom streamfile init */
|
||||
{
|
||||
STREAMFILE *new_sf = NULL;
|
||||
STREAMFILE* new_sf = NULL;
|
||||
riff_ogg_io_data io_data = {0};
|
||||
|
||||
io_data.patch_offset = patch_offset;
|
||||
|
Loading…
x
Reference in New Issue
Block a user