Fix some Ogg .wav [Kirara Kirara NTR (PC)]

This commit is contained in:
bnnm 2021-09-19 23:52:33 +02:00
parent 112aab1923
commit 5adae4db4c
2 changed files with 43 additions and 33 deletions

View File

@ -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;

View File

@ -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;