Add LPCM .w extension, cleanup

This commit is contained in:
bnnm 2021-10-09 12:51:33 +02:00
parent d2acaf3994
commit 54dd018c96
8 changed files with 211 additions and 181 deletions

View File

@ -567,6 +567,7 @@ static const char* extension_list[] = {
"vsv",
"vxn",
"w",
"waa",
"wac",
"wad",
@ -1118,7 +1119,8 @@ static const meta_info meta_info_list[] = {
{meta_XBOX_HLWAV, "Half-Life 2 .WAV header"},
{meta_MYSPD, "U-Sing .MYSPD header"},
{meta_HIS, "Her Interactive HIS header"},
{meta_PS2_AST, "KOEI AST header"},
{meta_AST_MV, "MicroVision AST header"},
{meta_AST_MMV, "Marvelous AST header"},
{meta_CAPDSP, "Capcom DSP header"},
{meta_DMSG, "Microsoft RIFF DMSG header"},
{meta_PONA_3DO, "Policenauts BGM header"},
@ -1146,7 +1148,7 @@ static const meta_info meta_info_list[] = {
{meta_DSP_XIII, "XIII dsp header"},
{meta_DSP_CABELAS, "Cabelas games .DSP header"},
{meta_PS2_ADM, "Dragon Quest V .ADM raw header"},
{meta_PS2_LPCM, "LPCM header"},
{meta_LPCM_SHADE, "Shade LPCM header"},
{meta_PS2_VMS, "VMS Header"},
{meta_XAU, "XPEC XAU header"},
{meta_GH3_BAR, "Guitar Hero III Mobile .bar"},

55
src/meta/ast_mmv.c Normal file
View File

@ -0,0 +1,55 @@
#include "meta.h"
#include "../coding/coding.h"
/* AST - from Marvelous(?) games [Katekyou Hitman Reborn! Dream Hyper Battle! (PS2), Binchou-tan: Shiawasegoyomi (PS2)] */
VGMSTREAM* init_vgmstream_ast_mmv(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset, data_size;
int loop_flag, channels, sample_rate, interleave;
/* checks */
if (!is_id32be(0x00,sf, "AST\0"))
goto fail;
/* .ast: from executables (usually found in bigfiles) */
if (!check_extensions(sf,"ast"))
goto fail;
data_size = read_u32le(0x04, sf);
if (data_size != get_streamfile_size(sf))
goto fail;
sample_rate = read_s32le(0x08,sf);
channels = read_32bitLE(0x0C,sf);
interleave = read_u32le(0x10,sf);
/* 0x14: number of blocks */
/* 0x18: ? (not fully related to size/time) */
/* 0x1c: f32 time */
loop_flag = 0;
start_offset = 0x100;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_AST_MMV;
vgmstream->num_samples = ps_bytes_to_samples(data_size - start_offset, channels);
vgmstream->sample_rate = sample_rate;
vgmstream->interleave_block_size = interleave;
vgmstream->layout_type = layout_interleave;
vgmstream->coding_type = coding_PSX;
read_string(vgmstream->stream_name,0x20, 0x20,sf);
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -2,74 +2,50 @@
#include "../coding/coding.h"
/* IKM - MiCROViSiON PS2 container [Zwei (PS2)] */
VGMSTREAM* init_vgmstream_ikm_ps2(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
static VGMSTREAM* init_vgmstream_ikm_ps2(STREAMFILE* sf) {
VGMSTREAM* v = NULL;
off_t start_offset;
int loop_flag, channel_count;
int loop_flag, channels;
/* checks */
if (!is_id32be(0x00,sf, "IKM\0"))
goto fail;
if (!check_extensions(sf,"ikm"))
goto fail;
/* 0x20: type 03? */
if (!is_id32be(0x40,sf, "AST\0"))
goto fail;
loop_flag = (read_s32le(0x14, sf) > 0);
channel_count = read_s32le(0x50, sf);
channels = read_s32le(0x50, sf);
start_offset = 0x800;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
v = allocate_vgmstream(channels, loop_flag);
if (!v) goto fail;
vgmstream->meta_type = meta_IKM;
vgmstream->sample_rate = read_s32le(0x44, sf);
vgmstream->num_samples = ps_bytes_to_samples(read_s32le(0x4c, sf), channel_count);
vgmstream->loop_start_sample = read_s32le(0x14, sf);
vgmstream->loop_end_sample = read_s32le(0x18, sf);
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10; /* @0x40 / channels */
v->meta_type = meta_IKM;
v->sample_rate = read_s32le(0x44, sf);
v->num_samples = ps_bytes_to_samples(read_s32le(0x4c, sf), channels);
v->loop_start_sample = read_s32le(0x14, sf);
v->loop_end_sample = read_s32le(0x18, sf);
v->coding_type = coding_PSX;
v->layout_type = layout_interleave;
v->interleave_block_size = 0x10; /* @0x40 / channels */
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
if (!vgmstream_open_stream(v, sf, start_offset))
goto fail;
return vgmstream;
return v;
fail:
close_vgmstream(vgmstream);
close_vgmstream(v);
return NULL;
}
/* IKM - MiCROViSiON PC container [Chaos Legion (PC), Legend of Galactic Heroes (PC)] */
VGMSTREAM* init_vgmstream_ikm_pc(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
static VGMSTREAM* init_vgmstream_ikm_pc(STREAMFILE* sf) {
VGMSTREAM* v = NULL;
off_t start_offset;
/* checks */
if (!is_id32be(0x00,sf, "IKM\0"))
goto fail;
if (!check_extensions(sf,"ikm"))
goto fail;
/* 0x20: type 01? */
/* find "OggS" start */
if (is_id32be(0x30,sf, "OggS")) {
if (is_id32be(0x30,sf, "OggS"))
start_offset = 0x30; /* Chaos Legion (PC) */
}
else if (is_id32be(0x800,sf, "OggS")) {
else
start_offset = 0x800; /* Legend of Galactic Heroes (PC) */
}
else {
goto fail;
}
{
ogg_vorbis_meta_info_t ovmi = {0};
@ -81,31 +57,23 @@ VGMSTREAM* init_vgmstream_ikm_pc(STREAMFILE* sf) {
ovmi.loop_flag = ovmi.loop_end > 0;
ovmi.stream_size = read_s32le(0x24, sf);
vgmstream = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
v = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
if (!v) goto fail;
}
return vgmstream;
return v;
fail:
close_vgmstream(vgmstream);
close_vgmstream(v);
return NULL;
}
/* IKM - MiCROViSiON PSP container [The Legend of Heroes: A Tear of Vermillion (PSP)] */
VGMSTREAM* init_vgmstream_ikm_psp(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
static VGMSTREAM* init_vgmstream_ikm_psp(STREAMFILE* sf) {
VGMSTREAM* v = NULL;
STREAMFILE* temp_sf = NULL;
off_t start_offset;
size_t data_size;
/* checks */
if (!is_id32be(0x00,sf, "IKM\0"))
goto fail;
if (!check_extensions(sf,"ikm"))
goto fail;
/* 0x20: type 00? */
if (!is_id32be(0x800,sf, "RIFF"))
goto fail;
@ -116,16 +84,43 @@ VGMSTREAM* init_vgmstream_ikm_psp(STREAMFILE* sf) {
temp_sf = setup_subfile_streamfile(sf, start_offset, data_size, "at3");
if (!temp_sf) goto fail;
vgmstream = init_vgmstream_riff(temp_sf);
if (!vgmstream) goto fail;
v = init_vgmstream_riff(temp_sf);
if (!v) goto fail;
vgmstream->meta_type = meta_IKM;
v->meta_type = meta_IKM;
close_streamfile(temp_sf);
return vgmstream;
return v;
fail:
close_streamfile(temp_sf);
close_vgmstream(vgmstream);
close_vgmstream(v);
return NULL;
}
/* IKM - MiCROViSiON container */
VGMSTREAM* init_vgmstream_ikm(STREAMFILE* sf) {
uint32_t type;
/* checks */
if (!is_id32be(0x00,sf, "IKM\0"))
goto fail;
if (!check_extensions(sf,"ikm"))
goto fail;
type = read_u32le(0x20, sf);
switch(type) {
case 0x00: /* The Legend of Heroes: A Tear of Vermillion (PSP) */
return init_vgmstream_ikm_psp(sf);
case 0x01: /* Chaos Legion (PC), Legend of Galactic Heroes (PC) */
return init_vgmstream_ikm_pc(sf);
case 0x03: /* Zwei (PS2) */
return init_vgmstream_ikm_ps2(sf);
default:
goto fail;
}
fail:
return NULL;
}

View File

@ -222,9 +222,7 @@ VGMSTREAM * init_vgmstream_leg(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_filp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ikm_ps2(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ikm_pc(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ikm_psp(STREAMFILE * streamFile);
VGMSTREAM* init_vgmstream_ikm(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_sfs(STREAMFILE * streamFile);
@ -444,7 +442,9 @@ VGMSTREAM * init_vgmstream_myspd(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_his(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_ast(STREAMFILE* streamFile);
VGMSTREAM* init_vgmstream_ast_mv(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_ast_mmv(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dmsg(STREAMFILE* streamFile);
@ -480,7 +480,7 @@ VGMSTREAM * init_vgmstream_ps2_wad(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_adm(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_lpcm(STREAMFILE* streamFile);
VGMSTREAM* init_vgmstream_lpcm_shade(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_bdsp(STREAMFILE* streamFile);

View File

@ -1,57 +1,48 @@
#include "meta.h"
#include "../coding/coding.h"
/* AST - from Koei and Marvelous games (same internal dev?) */
VGMSTREAM * init_vgmstream_ps2_ast(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, variant_type;
/* AST - from MicroVision lib games [P.T.O. IV (PS2), Naval Ops: Warship Gunner (PS2)] */
VGMSTREAM* init_vgmstream_ast_mv(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset, data_size, check;
int loop_flag, channels, interleave, sample_rate;
/* check extension */
if (!check_extensions(streamFile,"ast")) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x41535400) /* "AST\0" */
/* checks */
if (!is_id32be(0x00,sf, "AST\0"))
goto fail;
/* determine variant (after 0x10 is garbage/code data in type 1 until 0x800, but consistent in all songs) */
if (read_32bitBE(0x10,streamFile) == 0x00000000 || read_32bitBE(0x10,streamFile) == 0x20002000) {
variant_type = 1; /* Koei: P.T.O. IV (0x00000000), Naval Ops: Warship Gunner (0x20002000) */
channel_count = 2;
}
else {
variant_type = 2; /* Marvelous: Katekyoo Hitman Reborn! Dream Hyper Battle!, Binchou-tan: Shiawasegoyomi */
channel_count = read_32bitLE(0x0C,streamFile);
}
if (!check_extensions(sf,"ast"))
goto fail;
channels = 2;
sample_rate = read_s32le(0x04, sf);
interleave = read_u32le(0x08,sf);
data_size = read_u32le(0x0c,sf); /* may have garbage */
check = read_u32be(0x10, sf);
/* rest: null/garbage */
loop_flag = 0;
start_offset = 0x800;
/* there is a variation in .ikm (Zwei), with loops and different start offset */
if (check != 0x20002000 && /* NO:WG (garbage up to start) */
check != 0x00000000) /* PTO4 */
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
if (variant_type == 1) {
start_offset = 0x800;
vgmstream->sample_rate = read_32bitLE(0x04,streamFile);
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x0C,streamFile)-start_offset,channel_count);
vgmstream->interleave_block_size = read_32bitLE(0x08,streamFile);
}
else if (variant_type == 2) {
start_offset = 0x100;
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x04,streamFile)-start_offset,channel_count);
vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile);
}
else {
goto fail;
}
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = ps_bytes_to_samples(data_size - start_offset, channels);
vgmstream->interleave_block_size = interleave;
vgmstream->layout_type = layout_interleave;
vgmstream->coding_type = coding_PSX;
vgmstream->meta_type = meta_PS2_AST;
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_AST_MV;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

View File

@ -1,64 +1,51 @@
#include "meta.h"
#include "../util.h"
/* LPCM (from Ah! My Goddess (PS2)) */
VGMSTREAM * init_vgmstream_ps2_lpcm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("lpcm",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0,streamFile) != 0x4C50434D) /* LPCM */
goto fail;
loop_flag = read_32bitLE(0x8,streamFile);
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x10;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 48000;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = read_32bitLE(0x4,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x8,streamFile);
vgmstream->loop_end_sample = read_32bitLE(0xc,streamFile);
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 2;
vgmstream->meta_type = meta_PS2_LPCM;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
#include "meta.h"
/* LPCM - from Shade's 'Shade game library' (ShdLib) [Ah! My Goddess (PS2), Warship Gunner (PS2)] */
VGMSTREAM* init_vgmstream_lpcm_shade(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
uint32_t loop_flag, channels;
/* checks */
if (!is_id32be(0x00, sf, "LPCM"))
goto fail;
/* .w: real extension
* .lpcm: fake (header id) */
if (!check_extensions(sf, "w,lpcm"))
goto fail;
/* extra checks since header is kind of simple */
if (read_s32le(0x04,sf) * 0x02 * 2 > get_streamfile_size(sf)) /* data size is less than total samples */
goto fail;
if (read_u32le(0x10,sf) != 0) /* just in case */
goto fail;
start_offset = 0x800; /* assumed, closer to num_samples */
loop_flag = read_s32le(0x8,sf) != 0;
channels = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_LPCM_SHADE;
vgmstream->sample_rate = 48000;
vgmstream->num_samples = read_s32le(0x4,sf);
vgmstream->loop_start_sample = read_s32le(0x8,sf);
vgmstream->loop_end_sample = read_s32le(0xc,sf);
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -92,9 +92,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_musx,
init_vgmstream_leg,
init_vgmstream_filp,
init_vgmstream_ikm_ps2,
init_vgmstream_ikm_pc,
init_vgmstream_ikm_psp,
init_vgmstream_ikm,
init_vgmstream_sfs,
init_vgmstream_bg00,
init_vgmstream_sat_dvi,
@ -214,7 +212,8 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_xbox_hlwav,
init_vgmstream_myspd,
init_vgmstream_his,
init_vgmstream_ps2_ast,
init_vgmstream_ast_mmv,
init_vgmstream_ast_mv,
init_vgmstream_dmsg,
init_vgmstream_ngc_dsp_aaap,
init_vgmstream_ngc_dsp_konami,
@ -237,7 +236,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_dsp_xiii,
init_vgmstream_dsp_cabelas,
init_vgmstream_ps2_adm,
init_vgmstream_ps2_lpcm,
init_vgmstream_lpcm_shade,
init_vgmstream_dsp_bdsp,
init_vgmstream_ps2_vms,
init_vgmstream_xau,

View File

@ -507,7 +507,8 @@ typedef enum {
meta_PONA_3DO, /* Policenauts (3DO) */
meta_PONA_PSX, /* Policenauts (PSX) */
meta_XBOX_HLWAV, /* Half Life 2 (XBOX) */
meta_PS2_AST, /* Some KOEI game (PS2) */
meta_AST_MV,
meta_AST_MMV,
meta_DMSG, /* Nightcaster II - Equinox (XBOX) */
meta_NGC_DSP_AAAP, /* Turok: Evolution (NGC), Vexx (NGC) */
meta_PS2_STER, /* Juuni Kokuki: Kakukaku Taru Ou Michi Beni Midori no Uka */
@ -530,7 +531,7 @@ typedef enum {
meta_DSP_XIII, /* XIII, possibly more (Ubisoft header???) */
meta_DSP_CABELAS, /* Cabelas games */
meta_PS2_ADM, /* Dragon Quest V (PS2) */
meta_PS2_LPCM, /* Ah! My Goddess */
meta_LPCM_SHADE,
meta_DSP_BDSP, /* Ah! My Goddess */
meta_PS2_VMS, /* Autobahn Raser - Police Madness */
meta_XAU, /* XPEC Entertainment (Beat Down (PS2 Xbox), Spectral Force Chronicle (PS2)) */