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;
|
break;
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#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;
|
fmt->coding_type = coding_OGG_VORBIS;
|
||||||
break;
|
break;
|
||||||
#endif
|
#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));
|
(read_u16 (offset+0x26,sf));
|
||||||
uint32_t guid3 = read_u32be(offset+0x28,sf);
|
uint32_t guid3 = read_u32be(offset+0x28,sf);
|
||||||
uint32_t guid4 = read_u32be(offset+0x2c,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) */
|
/* PCM GUID (0x00000001,0000,0010,80,00,00,AA,00,38,9B,71) */
|
||||||
if (guid1 == 0x00000001 && guid2 == 0x00000010 && guid3 == 0x800000AA && guid4 == 0x00389B71) {
|
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:
|
default:
|
||||||
/* FFmpeg may play it */
|
/* 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;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +324,10 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
|||||||
off_t mwv_ctrl_offset = -1;
|
off_t mwv_ctrl_offset = -1;
|
||||||
|
|
||||||
|
|
||||||
/* check extension */
|
/* checks*/
|
||||||
|
if (!is_id32be(0x00,sf,"RIFF"))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
/* .lwav: to avoid hijacking .wav
|
/* .lwav: to avoid hijacking .wav
|
||||||
* .xwav: fake for Xbox games (not needed anymore)
|
* .xwav: fake for Xbox games (not needed anymore)
|
||||||
* .da: The Great Battle VI (PS1)
|
* .da: The Great Battle VI (PS1)
|
||||||
@ -355,21 +364,19 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check header */
|
riff_size = read_u32le(0x04,sf);
|
||||||
if (!is_id32be(0x00,sf,"RIFF"))
|
|
||||||
goto fail;
|
|
||||||
if (!is_id32be(0x08,sf, "WAVE"))
|
if (!is_id32be(0x08,sf, "WAVE"))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
riff_size = read_u32le(0x04,sf);
|
|
||||||
file_size = get_streamfile_size(sf);
|
file_size = get_streamfile_size(sf);
|
||||||
|
|
||||||
/* some games have wonky sizes, selectively fix to catch bad rips and new mutations */
|
/* some games have wonky sizes, selectively fix to catch bad rips and new mutations */
|
||||||
if (file_size != riff_size + 0x08) {
|
if (file_size != riff_size + 0x08) {
|
||||||
uint16_t codec = read_u16le(0x14,sf);
|
uint16_t codec = read_u16le(0x14,sf);
|
||||||
|
|
||||||
if (codec == 0x6771 && riff_size + 0x08 + 0x01 == file_size)
|
if ((codec & 0xFF00) == 0x6700 && riff_size + 0x08 + 0x01 == file_size)
|
||||||
riff_size += 0x01; /* [Shikkoku no Sharnoth (PC)] (Sony Sound Forge?) */
|
riff_size += 0x01; /* [Shikkoku no Sharnoth (PC), Only One 2 (PC)] (Sony Sound Forge?) */
|
||||||
|
|
||||||
else if (codec == 0x0069 && riff_size == file_size)
|
else if (codec == 0x0069 && riff_size == file_size)
|
||||||
riff_size -= 0x08; /* [Dynasty Warriors 3 (Xbox), BloodRayne (Xbox)] */
|
riff_size -= 0x08; /* [Dynasty Warriors 3 (Xbox), BloodRayne (Xbox)] */
|
||||||
@ -422,6 +429,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
|||||||
/* check for truncated RIFF */
|
/* check for truncated RIFF */
|
||||||
if (file_size != riff_size + 0x08) {
|
if (file_size != riff_size + 0x08) {
|
||||||
vgm_logi("RIFF: wrong expected size (report/re-rip?)\n");
|
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;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -774,8 +782,9 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
case coding_OGG_VORBIS: {
|
case coding_OGG_VORBIS: {
|
||||||
/* special handling of Liar-soft's buggy RIFF+Ogg made with Soundforge [Shikkoku no Sharnoth (PC)] */
|
/* special handling of Liar-soft's buggy RIFF+Ogg made with Soundforge/vorbis.acm [Shikkoku no Sharnoth (PC)],
|
||||||
STREAMFILE *temp_sf = setup_riff_ogg_streamfile(sf, start_offset, data_size);
|
* 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;
|
if (!temp_sf) goto fail;
|
||||||
|
|
||||||
vgmstream->codec_data = init_ogg_vorbis(temp_sf, 0x00, get_streamfile_size(temp_sf), NULL);
|
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;
|
int FormatChunkFound = 0, DataChunkFound = 0;
|
||||||
|
|
||||||
|
|
||||||
/* check extension, case insensitive */
|
/* checks */
|
||||||
|
if (!is_id32be(0x00,sf, "RIFX"))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (!check_extensions(sf, "wav,lwav"))
|
if (!check_extensions(sf, "wav,lwav"))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* check header */
|
|
||||||
if (!is_id32be(0x00,sf, "RIFX"))
|
|
||||||
goto fail;
|
|
||||||
if (!is_id32be(0x08,sf, "WAVE"))
|
if (!is_id32be(0x08,sf, "WAVE"))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
@ -3,22 +3,22 @@
|
|||||||
#include "deblock_streamfile.h"
|
#include "deblock_streamfile.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
off_t patch_offset;
|
uint32_t patch_offset;
|
||||||
} riff_ogg_io_data;
|
} 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) {
|
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(dest, offset, length, sf);
|
size_t bytes = read_streamfile(dst, offset, length, sf);
|
||||||
|
|
||||||
/* has garbage init Oggs pages, patch bad flag */
|
/* has garbage init Oggs pages, patch bad flag */
|
||||||
if (data->patch_offset && data->patch_offset >= offset && data->patch_offset < offset + bytes) {
|
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);
|
VGM_ASSERT(dst[data->patch_offset - offset] != 0x02, "RIFF Ogg: bad patch offset at %x\n", data->patch_offset);
|
||||||
dest[data->patch_offset - offset] = 0x00;
|
dst[data->patch_offset - offset] = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes;
|
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;
|
size_t segments, bytes, page_size;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -43,8 +43,8 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* patches Ogg with weirdness */
|
/* patches Ogg with weirdness */
|
||||||
static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE *sf, off_t start, size_t size) {
|
static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE* sf, uint32_t start, size_t size) {
|
||||||
off_t patch_offset = 0;
|
uint32_t patch_offset = 0;
|
||||||
size_t real_size = size;
|
size_t real_size = size;
|
||||||
uint8_t buf[0x1000];
|
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 */
|
/* 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
|
//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;
|
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
|
//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 */
|
/* first page is ok */
|
||||||
page_size = ogg_get_page(buf, sizeof(buf), offset, temp_sf);
|
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);
|
page_size = ogg_get_page(buf, sizeof(buf), offset, temp_sf);
|
||||||
if (page_size == 0) break;
|
if (page_size == 0) break;
|
||||||
|
|
||||||
if (get_u32be(buf + 0x00) != 0x4f676753) /* "OggS" */
|
if (get_u32be(buf + 0x00) != get_id32be("OggS"))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (get_u16be(buf + 0x04) == 0x0002) { /* start page flag */
|
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);
|
close_streamfile(temp_sf);
|
||||||
|
|
||||||
if (patch_offset == 0)
|
/* no need to patch initial flag */
|
||||||
return NULL;
|
//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 */
|
/* 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 chunk_size = sizeof(buf); /* not worth testing more */
|
||||||
size_t max_size = size;
|
size_t max_size = size;
|
||||||
size_t pos;
|
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);
|
pos = read_streamfile(buf, read_offset, chunk_size, sf);
|
||||||
if (read_offset < 0 || pos <= 0x1a) return NULL;
|
if (read_offset < 0 || pos <= 0x1a) return NULL;
|
||||||
|
|
||||||
pos -= 0x1a; /* at least one OggS page */
|
pos -= 0x1a; /* at least one OggS page */
|
||||||
while (pos > 0) {
|
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 */
|
if (get_u16be(buf + pos + 0x04) == 0x0004) { /* last page flag is ok */
|
||||||
real_size = max_size;
|
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 */
|
/* actual custom streamfile init */
|
||||||
{
|
{
|
||||||
STREAMFILE *new_sf = NULL;
|
STREAMFILE* new_sf = NULL;
|
||||||
riff_ogg_io_data io_data = {0};
|
riff_ogg_io_data io_data = {0};
|
||||||
|
|
||||||
io_data.patch_offset = patch_offset;
|
io_data.patch_offset = patch_offset;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user