Merge pull request #1386 from bnnm/lsf-etc

- Fix some .lsf [Agaju (Gizmondo), Chicane (Gizmondo))]
- Fix some .seg [Eragon (X360)]
- Fix some broken .bnk [Fat Princess (PS3)]
- Add .imf extension [Colors (Gizmondo)]
- Remove .bd3 extension (use .hd3)
- Remove .lrmb extension (use .lrmh)
- Remove fake extension .bh2pcm (use .dat + TXTH)
This commit is contained in:
bnnm 2023-07-01 01:44:04 +02:00 committed by GitHub
commit 740a4048f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 2272 additions and 2228 deletions

View File

@ -3,19 +3,23 @@
import glob, os, re
#TODO maybe sort by meta order list in vgmstream.c
#TODO fix ??? descriptions
#TODO fix some "ext + ext" exts
#TODO improve some ubi formats
#TODO improve dsp/ubi/ea formats
#TODO detect subfile/init_x calls that aren't VGMSTREAM * init_
#TODO detect MPEG_x, OPUS_x subtypes
#TODO ignore some check extensions
#TODO include common idstrings (first is_id32be() / is_id32le / get_id32be / get_id32be)
#TODO ignore some check extensions?
#TODO maybe include common idstrings (first is_id32be() / is_id32le / get_id32be / get_id32be)
# > after first valid init?
META_FILES = '../**/meta/*.c'
FORMAT_FILES = '../**/formats.c'
IS_PRINT_INFO = False #false = write
META_SRC = '../**/meta/*.c'
FORMAT_SRC = '../**/formats.c'
SORT_SRC = '../**/vgmstream.c'
FORMAT_DOC = '../**/FORMATS.md'
DUMP_DOC = 'formats-info.md'
IS_SORT = True #sorts metas lines based on LIST_SRC
IS_PRINT_DOC = False #echo list
IS_DUMP_DOC = False #creates DUMP_DOC
IS_UPDATE_DOC = True #updates FORMAT_DOC
#VGMSTREAM * init_vgmstream_9tav(STREAMFILE *sf) #allow static since it's used in some cases
RE_INIT = re.compile(r"VGMSTREAM[ ]*\*[ ]*init_vgmstream_([A-Za-z0-9_]+)\(.+\)")
@ -41,10 +45,13 @@ RE_OLD_EXTCHECK = re.compile(r"if[ ]*\(strcasecmp\([ ]*\"(.+)\"[ ]*,filename_ext
# formats.c extract
RE_FORMATS_META = re.compile(r"{meta_([A-Z0-9][A-Za-z0-9_]+)[ ]*,[ ]* \"(.+)\"[ ]*}")
# vgmstream.c meta call extract
RE_SORT_INIT = re.compile(r"[ ]+init_vgmstream_([A-Za-z0-9_]+),")
FILES_SKIP = [
'txth.c','txtp.c','genh.c',
'silence.c', 'mp4_faac.c', 'deblock_streamfile.c',
'ps_headerless.c', 'zwdsp.c', 'ngc_bh2pcm.c',
'ps_headerless.c', 'zwdsp.c',
]
EXT_RENAMES = {'...': '(any)', '': '(extensionless)'}
@ -53,8 +60,7 @@ META_IGNORES = ['meta_type', 'meta_t']
CODING_IGNORES = ['coding_type', 'coding_t', 'FFmpeg', 'SILENCE']
SUBFILES_IGNORES = ['subkey', 'silence', 'silence_container']
# various codecs that
# detect better various codecs that use a generic coding_XXX
INIT_CODECS = {
re.compile(r'init_ffmpeg_aac\('): 'AAC',
re.compile(r'init_ffmpeg_xwma\('): 'XWMA',
@ -86,6 +92,7 @@ class MetaInit:
class MetaFile:
def __init__(self, file):
self.fileinfo = os.path.basename(file)
self.order = 9999
# divide each file into sub-metas since some .c have a bunch of them
self.curr = MetaInit('default') #shouldn't be used but...
self.inits = [self.curr]
@ -132,6 +139,7 @@ class App:
def __init__(self):
self.infos = []
self.desc_metas = {}
self.lines = []
def extract_extensions(self, line):
@ -160,7 +168,7 @@ class App:
def parse_files(self):
infos = self.infos
files = glob.glob(META_FILES, recursive=True)
files = glob.glob(META_SRC, recursive=True)
for file in files:
info = MetaFile(file)
with open(file, 'r', encoding='utf-8') as f:
@ -201,7 +209,8 @@ class App:
def parse_formats(self):
desc_metas = self.desc_metas
files = glob.glob(FORMAT_FILES, recursive=True)
files = glob.glob(FORMAT_SRC, recursive=True)
for file in files:
with open(file, 'r', encoding='utf-8') as f:
for line in f:
@ -210,13 +219,41 @@ class App:
continue
meta, desc = items[0]
desc_metas[meta] = desc
def print(self):
def sort_files(self):
inits_order = {}
# get process list order
files = glob.glob(SORT_SRC, recursive=True)
order = 0
for file in files:
with open(file, 'r', encoding='utf-8') as f:
for line in f:
items = self.extract_regex(line, RE_SORT_INIT)
if not items or len(items) != 1:
continue
init = items[0]
inits_order[init] = order
order += 1
# update (could be done on first pass or maybe in sort() but it's a bit specialized)
infos = self.infos
for info in infos:
for init in info.inits:
order = inits_order.get(init.name)
#print(init, order)
if order is not None and info.order > order:
info.order = order
infos.sort(key=lambda x: x.order) #, reverse=True
def prepare_results(self):
desc_metas = self.desc_metas
infos = self.infos
lines = []
lines = self.lines
for info in infos:
#info.sort()
if info.fileinfo in FILES_SKIP:
@ -228,7 +265,6 @@ class App:
# fileinfo += " (%s)" % (metas)
lines.append(fileinfo)
if info.metas:
for meta in info.metas:
desc = desc_metas.get(meta, '???')
@ -267,16 +303,67 @@ class App:
#lines.append('')
if IS_PRINT_INFO:
print('\n'.join(lines))
else:
with open('formats-info.md', 'w', encoding='utf-8') as f:
f.write('\n'.join(lines))
def update_doc(self):
new_lines = self.lines
files = glob.glob(FORMAT_DOC, recursive=True)
if not files:
print("format doc (%s) not found" % FORMAT_DOC)
return
doc_lines = []
file = files[0]
with open(file, 'r', encoding='utf-8') as f:
is_updating = False
for line in f:
line = line.strip()
# find list section, add all current lines and ignore old ones until next section
if line.startswith('### List'):
is_updating = True
doc_lines.append(line)
doc_lines += new_lines
doc_lines.append('')
continue
# next section
if is_updating and line.startswith('#'):
is_updating = False
if not is_updating:
doc_lines.append(line)
with open(file, 'w', encoding='utf-8', newline='\n') as f:
f.write('\n'.join(doc_lines))
def dump_doc(self):
lines = self.lines
with open(DUMP_DOC, 'w', encoding='utf-8') as f:
f.write('\n'.join(lines))
def print_doc(self):
lines = self.lines
print('\n'.join(lines))
def process(self):
self.parse_files()
self.parse_formats()
self.print()
if IS_SORT:
self.sort_files()
self.prepare_results()
if IS_PRINT_DOC:
self.print_doc()
if IS_DUMP_DOC:
self.dump_doc()
if IS_UPDATE_DOC:
self.update_doc()
App().process()

File diff suppressed because it is too large Load Diff

View File

@ -132,8 +132,8 @@ as explained below, but often will use default values. Accepted codec strings:
#
# - MSADPCM Microsoft ADPCM (mono/stereo)
# * For some PC games
# * Interleave (frame size) varies, often multiple of 0x100 [required]
#
# * Interleave (frame size) varies, often 0x2c/0x8c/0x100/0x400 and max 0x800 [required]
# - AICA Yamaha AICA ADPCM (mono/stereo)
# * For some Dreamcast games, and some arcade (Naomi) games
# * Special interleave is multiple of 0x1

View File

@ -449,7 +449,7 @@ int decode_get_samples_per_frame(VGMSTREAM* vgmstream) {
return 28;
case coding_PSX_cfg:
case coding_PSX_pivotal:
return (vgmstream->interleave_block_size - 0x01) * 2; /* size 0x01 header */
return (vgmstream->frame_size - 0x01) * 2; /* size 0x01 header */
case coding_EA_XA:
case coding_EA_XA_int:
@ -669,7 +669,7 @@ int decode_get_frame_size(VGMSTREAM* vgmstream) {
return 0x10;
case coding_PSX_cfg:
case coding_PSX_pivotal:
return vgmstream->interleave_block_size;
return vgmstream->frame_size;
case coding_EA_XA:
return 0x1E;
@ -998,14 +998,14 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_psx_configurable(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do,
vgmstream->interleave_block_size, vgmstream->codec_config);
vgmstream->frame_size, vgmstream->codec_config);
}
break;
case coding_PSX_pivotal:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_psx_pivotal(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do,
vgmstream->interleave_block_size);
vgmstream->frame_size);
}
break;
case coding_HEVAG:

View File

@ -99,13 +99,11 @@ static const char* extension_list[] = {
"bcstm",
"bcwav",
"bcv", //txth/reserved [The Bigs (PSP)]
"bd3",
"bfstm",
"bfwav",
"bg00",
"bgm",
"bgw",
"bh2pcm",
"bigrp",
"bik",
"bika", //fake extension for .bik (to be removed)
@ -216,6 +214,7 @@ static const char* extension_list[] = {
"h4m",
"hab",
"hca",
"hd3",
"hdr",
"hdt",
"hgc1",
@ -249,6 +248,7 @@ static const char* extension_list[] = {
"ilv", //txth/reserved [Star Wars Episode III (PS2)]
"ima",
"imc",
"imf",
"imx",
"int",
"is14",
@ -315,7 +315,7 @@ static const char* extension_list[] = {
"lpcm",
"lpk",
"lps",
"lrmb",
"lrmh",
"lse",
"lsf",
"lstm", //fake extension for .stm
@ -844,7 +844,7 @@ static const coding_info coding_info_list[] = {
{coding_TGC, "Tiger Game.com 4-bit ADPCM"},
{coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"},
{coding_L5_555, "Level-5 0x555 4-bit ADPCM"},
{coding_LSF, "lsf 4-bit ADPCM"},
{coding_LSF, "Gizmondo Studios Helsingborg LSF 4-bit ADPCM"},
{coding_MTAF, "Konami MTAF 4-bit ADPCM"},
{coding_MTA2, "Konami MTA2 4-bit ADPCM"},
{coding_MC3, "Paradigm MC3 3-bit ADPCM"},
@ -1173,7 +1173,7 @@ static const meta_info meta_info_list[] = {
{meta_SSS, "Namco .SSS raw header"},
{meta_PS2_GCM, "Namco GCM header"},
{meta_SMPL, "Skonec SMPL header"},
{meta_PS2_MSA, "Success .MSA header"},
{meta_MSA, "Success .MSA header"},
{meta_VOI, "Irem .VOI header"},
{meta_NGC_PDT, "Hudson .PDT header"},
{meta_NGC_RKV, "Legacy of Kain - Blood Omen 2 RKV GC header"},
@ -1207,7 +1207,7 @@ static const meta_info meta_info_list[] = {
{meta_VGS_PS, "Princess Soft VGS header"},
{meta_PS2_IAB, "Runtime .IAB header"},
{meta_VS_STR, "Square .VS STRx header"},
{meta_LSF_N1NJ4N, ".lsf !n1nj4n header"},
{meta_LSF_N1NJ4N, "Gizmondo Studios Helsingborg LSF header"},
{meta_XWAV, "feelplus XWAV header"},
{meta_RAW_SNDS, "PC .snds raw header"},
{meta_PS2_WMUS, "assumed The Warriors Sony ADPCM by .wmus extension"},
@ -1260,7 +1260,7 @@ static const meta_info meta_info_list[] = {
{meta_EA_BNK, "Electronic Arts BNK header"},
{meta_SK_AUD, "Silicon Knights AUD header"},
{meta_AHX, "CRI AHX header"},
{meta_STM, "Angel Studios/Rockstar San Diego STMA header"},
{meta_STMA, "Angel Studios/Rockstar San Diego STMA header"},
{meta_BINK, "RAD Game Tools Bink header"},
{meta_EA_SNU, "Electronic Arts SNU header"},
{meta_AWC, "Rockstar AWC header"},

View File

@ -484,6 +484,7 @@
<ClCompile Include="meta\mp4.c" />
<ClCompile Include="meta\mp4_faac.c" />
<ClCompile Include="meta\mpeg.c" />
<ClCompile Include="meta\msa.c" />
<ClCompile Include="meta\msb_msh.c" />
<ClCompile Include="meta\msf.c" />
<ClCompile Include="meta\msf_banpresto.c" />
@ -507,7 +508,6 @@
<ClCompile Include="meta\nds_strm.c" />
<ClCompile Include="meta\nds_strm_ffta2.c" />
<ClCompile Include="meta\ngc_adpdtk.c" />
<ClCompile Include="meta\ngc_bh2pcm.c" />
<ClCompile Include="meta\ngc_dsp_konami.c" />
<ClCompile Include="meta\ngc_dsp_mpds.c" />
<ClCompile Include="meta\ngc_dsp_std.c" />
@ -562,7 +562,6 @@
<ClCompile Include="meta\ps2_mcg.c" />
<ClCompile Include="meta\ps2_mic.c" />
<ClCompile Include="meta\ps2_mihb.c" />
<ClCompile Include="meta\ps2_msa.c" />
<ClCompile Include="meta\ps2_p2bt.c" />
<ClCompile Include="meta\ps2_pcm.c" />
<ClCompile Include="meta\ps2_rnd.c" />
@ -599,9 +598,9 @@
<ClCompile Include="meta\rsd.c" />
<ClCompile Include="meta\rstm_rockstar.c" />
<ClCompile Include="meta\rwax.c" />
<ClCompile Include="meta\rwsd.c" />
<ClCompile Include="meta\rws_809.c" />
<ClCompile Include="meta\rws_80d.c" />
<ClCompile Include="meta\rwsd.c" />
<ClCompile Include="meta\rxws.c" />
<ClCompile Include="meta\s3v.c" />
<ClCompile Include="meta\sab.c" />
@ -642,7 +641,7 @@
<ClCompile Include="meta\sspr.c" />
<ClCompile Include="meta\ster.c" />
<ClCompile Include="meta\sthd.c" />
<ClCompile Include="meta\stm.c" />
<ClCompile Include="meta\stma.c" />
<ClCompile Include="meta\strm_abylight.c" />
<ClCompile Include="meta\str_snds.c" />
<ClCompile Include="meta\str_wav.c" />

View File

@ -1273,6 +1273,9 @@
<ClCompile Include="meta\mpeg.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\msa.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\msb_msh.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -1342,9 +1345,6 @@
<ClCompile Include="meta\ngc_adpdtk.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ngc_bh2pcm.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ngc_dsp_konami.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -1507,9 +1507,6 @@
<ClCompile Include="meta\ps2_mihb.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_msa.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_p2bt.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -1618,15 +1615,15 @@
<ClCompile Include="meta\rwax.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\rwsd.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\rws_809.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\rws_80d.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\rwsd.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\rxws.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -1747,7 +1744,7 @@
<ClCompile Include="meta\sthd.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\stm.c">
<ClCompile Include="meta\stma.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\strm_abylight.c">

View File

@ -11,7 +11,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
uint32_t start_offset, stream_offset, name_offset = 0;
uint32_t stream_size, interleave = 0;
int channels = 0, loop_flag, sample_rate, big_endian;
int loop_start = 0, loop_end = 0;
int32_t loop_start = 0, loop_end = 0;
uint32_t center_note, center_fine, flags;
uint32_t atrac9_info = 0;
@ -43,7 +43,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
if (!check_extensions(sf, "bnk"))
return NULL;
uint32_t sblk_offset, sblk_size, data_offset, data_size, zlsd_size = 0;
uint32_t sblk_offset, data_offset, data_size;
int parts, sblk_version;
parts = read_u32(0x04,sf);
@ -51,17 +51,19 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
return NULL;
/* in theory a bank can contain multiple blocks */
/* section sizes don't include padding (sometimes aligned to 0x10/0x800) */
sblk_offset = read_u32(0x08,sf);
sblk_size = read_u32(0x0c,sf);
//sblk_size = read_u32(0x0c,sf);
data_offset = read_u32(0x10,sf);
data_size = read_u32(0x14,sf);
if (sblk_offset >= 0x20) {
/* ZLSD small footer, rare in earlier versions and more common later [Yakuza 6's Puyo Puyo (PS4)] */
//zlsd_offset = read_u32(0x18,sf);
zlsd_size = read_u32(0x1c,sf);
}
if (sblk_offset + sblk_size + data_size + zlsd_size != get_streamfile_size(sf))
/* ZLSD small footer, rare in earlier versions and more common later [Yakuza 6's Puyo Puyo (PS4)] */
//if (sblk_offset >= 0x20) {
// zlsd_offset = read_u32(0x18,sf);
// zlsd_size = read_u32(0x1c,sf);
//}
if (sblk_offset > 0x20)
return NULL;
/* SE banks, also used for music. Most table fields seems reserved/defaults and
@ -231,7 +233,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
}
//;VGM_LOG("BNK: subsongs %i, table2_entry=%lx, table3_entry=%lx\n", total_subsongs,table2_entry_offset,table3_entry_offset);
//;VGM_LOG("BNK: subsongs %i, table2_entry=%x, table3_entry=%x\n", total_subsongs,table2_entry_offset,table3_entry_offset);
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* this means some subsongs repeat streams, that can happen in some sfx banks, whatevs */
@ -322,6 +324,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
break;
default:
VGM_LOG("BNK: missing version\n");
goto fail;
}
@ -469,8 +472,10 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
case 0x02: /* ATRAC9 mono */
case 0x05: /* ATRAC9 stereo */
if (read_u32(start_offset+0x08,sf) + 0x08 != extradata_size) /* repeat? */
if (read_u32(start_offset+0x08,sf) + 0x08 != extradata_size) { /* repeat? */
VGM_LOG("BNK: unknown subtype\n");
goto fail;
}
channels = (type == 0x02) ? 1 : 2;
atrac9_info = read_u32be(start_offset+0x0c,sf);
@ -493,8 +498,10 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
case 0x0f:
case 0x10:
type = read_u16(start_offset+0x00,sf);
if (read_u32(start_offset+0x04,sf) != 0x01) /* type? */
if (read_u32(start_offset+0x04,sf) != 0x01) { /* type? */
VGM_LOG("BNK: unknown subtype\n");
goto fail;
}
extradata_size = 0x10 + read_u32(start_offset+0x08,sf); /* 0x80 for AT9, 0x10 for PCM/PS-ADPCM */
/* 0x0c: null? */

View File

@ -1,120 +1,101 @@
#include "meta.h"
#include "../coding/coding.h"
/* HD3+BD3 - Sony PS3 bank format [Elevator Action Deluxe (PS3), R-Type Dimensions (PS3)] */
VGMSTREAM * init_vgmstream_hd3_bd3(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamHeader = NULL;
off_t start_offset;
int channel_count, loop_flag, sample_rate;
size_t interleave, stream_size;
int total_subsongs, target_subsong = streamFile->stream_index;
/* checks */
if (!check_extensions(streamFile, "bd3"))
goto fail;
streamHeader = open_streamfile_by_ext(streamFile,"hd3");
if (!streamHeader) goto fail;
if (read_32bitBE(0x00,streamHeader) != 0x50334844) /* "P3HD" */
goto fail;
/* 0x04: section size (not including first 0x08) */
/* 0x08: version? 0x00020000 */
/* 0x10: "P3PG" offset (seems mostly empty and contains number of subsongs towards the end) */
/* 0x14: "P3TN" offset (some kind of config?) */
/* 0x18: "P3VA" offset (VAG headers) */
{
off_t section_offset = read_32bitBE(0x18,streamHeader);
off_t header_offset;
size_t section_size;
int i, entries, is_bgm = 0;
if (read_32bitBE(section_offset+0x00,streamHeader) != 0x50335641) /* "P3VA" */
goto fail;
section_size = read_32bitBE(section_offset+0x04,streamHeader); /* (not including first 0x08) */
/* 0x08 size of all subsong headers + 0x10 */
entries = read_32bitBE(section_offset+0x14,streamHeader);
/* often there is an extra subsong than written, but may be padding instead */
if (read_32bitBE(section_offset + 0x20 + entries*0x10 + 0x04,streamHeader)) /* has sample rate */
entries += 1;
if (entries * 0x10 > section_size) /* just in case, padding after entries is possible */
goto fail;
/* autodetect use of N bank entries as channels [Elevator Action Deluxe (PS3)] */
if (entries > 1) {
size_t channel_size = read_32bitBE(section_offset+0x20+0x08,streamHeader);
is_bgm = 1;
for (i = 1; i < entries; i++) {
size_t next_size = read_32bitBE(section_offset+0x20+(i*0x10)+0x08,streamHeader);
if (channel_size != next_size) {
is_bgm = 0;
break;
}
}
}
if (is_bgm) {
total_subsongs = 1;
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
header_offset = section_offset+0x20+(0)*0x10;
start_offset = read_32bitBE(header_offset+0x00,streamHeader); /* 0x00 */
sample_rate = read_32bitBE(header_offset+0x04,streamHeader);
stream_size = get_streamfile_size(streamFile);
if (read_32bitBE(header_offset+0x0c,streamHeader) != -1)
goto fail;
channel_count = entries;
interleave = stream_size / channel_count;
}
else {
total_subsongs = entries;
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
header_offset = section_offset+0x20+(target_subsong-1)*0x10;
start_offset = read_32bitBE(header_offset+0x00,streamHeader);
sample_rate = read_32bitBE(header_offset+0x04,streamHeader);
stream_size = read_32bitBE(header_offset+0x08,streamHeader);
if (read_32bitBE(header_offset+0x0c,streamHeader) != -1)
goto fail;
channel_count = 1;
interleave = 0;
}
}
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count);
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = stream_size;
vgmstream->meta_type = meta_HD3_BD3;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
vgmstream->interleave_block_size = interleave;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
close_streamfile(streamHeader);
return vgmstream;
fail:
close_streamfile(streamHeader);
close_vgmstream(vgmstream);
return NULL;
}
#include "meta.h"
#include "../coding/coding.h"
/* HD3+BD3 - Sony PS3 bank format [Elevator Action Deluxe (PS3), R-Type Dimensions (PS3)] */
VGMSTREAM* init_vgmstream_hd3_bd3(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sb = NULL;
uint32_t stream_offset, stream_size;
int channels, loop_flag, sample_rate, interleave;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
if (!is_id32be(0x00,sf, "P3HD"))
return NULL;
if (!check_extensions(sf, "hd3"))
return NULL;
sb = open_streamfile_by_ext(sf,"bd3");
if (!sf) goto fail;
/* 0x04: section size (not including first 0x08) */
/* 0x08: version? 0x00020000 */
/* 0x10: "P3PG" offset (seems mostly empty and contains number of subsongs towards the end) */
/* 0x14: "P3TN" offset (some kind of config/volumes/etc?) */
/* 0x18: "P3VA" offset (VAG headers) */
{
uint32_t section_offset = read_u32be(0x18,sf);
uint32_t section_size;
int entries;
if (!is_id32be(section_offset+0x00,sf, "P3VA"))
goto fail;
section_size = read_u32be(section_offset+0x04,sf); /* (not including first 0x08) */
/* 0x08 size of all subsong headers + 0x10 */
entries = read_u32be(section_offset+0x14,sf);
/* often there is an extra subsong than written, but may be padding instead */
if (read_u32be(section_offset + 0x20 + entries*0x10 + 0x04,sf)) /* has sample rate */
entries += 1;
if (entries * 0x10 > section_size) /* just in case, padding after entries is possible */
goto fail;
/* very often subsongs make stereo pairs (even with many), this detects simple cases */ //TODO check if there is some flag or remove hack
bool is_bgm = false;
if (entries == 2) {
uint32_t curr_size = read_u32be(section_offset+0x20+(0*0x10)+0x08,sf);
uint32_t next_size = read_u32be(section_offset+0x20+(1*0x10)+0x08,sf);
is_bgm = (curr_size == next_size);
}
if (is_bgm) {
total_subsongs = 1;
channels = entries;
}
else {
total_subsongs = entries;
channels = 1;
}
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
uint32_t header_offset = section_offset+0x20+(target_subsong-1)*0x10;
stream_offset = read_u32be(header_offset+0x00,sf);
sample_rate = read_u32be(header_offset+0x04,sf);
stream_size = read_u32be(header_offset+0x08,sf) * channels;
interleave = stream_size / channels;
if (read_s32be(header_offset+0x0c,sf) != -1)
goto fail;
}
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels);
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = stream_size;
vgmstream->meta_type = meta_HD3_BD3;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = (channels == 1) ? layout_none : layout_interleave;
vgmstream->interleave_block_size = interleave;
if (!vgmstream_open_stream(vgmstream, sb, stream_offset))
goto fail;
close_streamfile(sb);
return vgmstream;
fail:
close_streamfile(sb);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -3,9 +3,10 @@
#include "lrmd_streamfile.h"
/* LRMD - Sony/SCEI's format (Loco Roco Music Data?) [LocoRoco 2 (PSP), LocoRoco: Midnight Carnival (PSP)] */
VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * sf_h = NULL, *temp_sf = NULL;
VGMSTREAM* init_vgmstream_lrmd(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sb = NULL;
STREAMFILE* temp_sf = NULL;
off_t stream_offset, section1_offset, section2_offset, basename_offset, subname_offset;
size_t stream_size, max_chunk, block_size = 0, chunk_start, chunk_size;
int loop_flag, channel_count, sample_rate, layers;
@ -14,39 +15,41 @@ VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) {
/* checks */
if (!check_extensions(sf, "lrmb"))
goto fail;
sf_h = open_streamfile_by_ext(sf, "lrmh");
if (!sf_h) goto fail;
if (read_u32be(0x00, sf_h) != 0x4C524D44) /* "LRMD" */
goto fail;
if (!is_id32be(0x00, sf, "LRMD"))
return NULL;
/* 0x00: version 1? */
/* 0x08: header size */
/* 0x0c: body size */
if (read_u32be(0x10, sf_h) != 0x52455144) /* "REQD" */
goto fail;
if (!is_id32be(0x10, sf, "REQD"))
return NULL;
/* 0x14: chunk size */
/* 0x18: null? */
/* 0x1c: 1? */
/* .lrmh+lrmb: actual extensions */
if (!check_extensions(sf, "lrmh"))
goto fail;
sb = open_streamfile_by_ext(sf, "lrmb");
if (!sb) goto fail;
/* 0x20: null */
basename_offset = read_u32le(0x24, sf_h);
if (read_u16le(0x28, sf_h) != 0x4000) { /* pitch? */
basename_offset = read_u32le(0x24, sf);
if (read_u16le(0x28, sf) != 0x4000) { /* pitch? */
VGM_LOG("LRMD: unknown value\n");
goto fail;
}
max_chunk = read_u16le(0x2a, sf_h);
num_samples = read_u32le(0x2c, sf_h);
max_chunk = read_u16le(0x2a, sf);
num_samples = read_u32le(0x2c, sf);
/* 0x30: null? */
/* 0x34: data size for all layers */
layers = read_u32le(0x38, sf_h);
section1_offset = read_u32le(0x3c, sf_h);
layers = read_u32le(0x38, sf);
section1_offset = read_u32le(0x3c, sf);
/* 0x40: lip table entries */
/* 0x44: lip table offset */
/* 0x48: section2 flag */
section2_offset = read_u32le(0x4c, sf_h);
section2_offset = read_u32le(0x4c, sf);
/* 0x40: section3 flag */
/* 0x44: section3 (unknown) */
@ -68,11 +71,11 @@ VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) {
int layer_channels;
/* not too sure but needed for LR2's muihouse last 3 layers */
layer_channels = read_u8(header_offset + 0x0d, sf_h) != 0 ? 1 : 2;
layer_channels = read_u8(header_offset + 0x0d, sf) != 0 ? 1 : 2;
if (i + 1 == target_subsong) {
/* 0x00: null */
subname_offset = read_u32le(header_offset + 0x04, sf_h);
subname_offset = read_u32le(header_offset + 0x04, sf);
/* 0x08: unk */
/* 0x0c: flags? */
/* 0x10: null? */
@ -94,9 +97,9 @@ VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) {
/* section2: loops */
/* 0x00: offset to "loop" name */
if (section2_offset > 0) {
loop_end = read_u32le(section2_offset + 0x04, sf_h);
loop_start = read_u32le(section2_offset + 0x08, sf_h);
loop_flag = read_u32le(section2_offset + 0x0c, sf_h);
loop_end = read_u32le(section2_offset + 0x04, sf);
loop_start = read_u32le(section2_offset + 0x08, sf);
loop_flag = read_u32le(section2_offset + 0x0c, sf);
}
else {
loop_end = 0;
@ -106,7 +109,7 @@ VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) {
/* data de-interleave */
temp_sf = setup_lrmd_streamfile(sf, block_size, chunk_start, chunk_size);
temp_sf = setup_lrmd_streamfile(sb, block_size, chunk_start, chunk_size);
if (!temp_sf) goto fail;
stream_offset = 0x00;
@ -142,23 +145,23 @@ VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) {
/* name custom main + layer name */
{
int name_len = read_string(vgmstream->stream_name, STREAM_NAME_SIZE - 1, basename_offset, sf_h);
int name_len = read_string(vgmstream->stream_name, STREAM_NAME_SIZE - 1, basename_offset, sf);
strcat(vgmstream->stream_name, "/");
name_len++;
read_string(vgmstream->stream_name + name_len, STREAM_NAME_SIZE - name_len, subname_offset, sf_h);
read_string(vgmstream->stream_name + name_len, STREAM_NAME_SIZE - name_len, subname_offset, sf);
}
if (!vgmstream_open_stream(vgmstream, temp_sf, stream_offset))
goto fail;
close_streamfile(sf_h);
close_streamfile(sb);
close_streamfile(temp_sf);
return vgmstream;
fail:
close_streamfile(sf_h);
close_streamfile(sb);
close_streamfile(temp_sf);
close_vgmstream(vgmstream);
return NULL;

View File

@ -1,43 +1,85 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* .lsf - from Atod games [Fastlane Street Racing (iPhone), Chicane Street Racing prototype (Gizmondo)] */
VGMSTREAM * init_vgmstream_lsf_n1nj4n(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
size_t file_size;
/* .lsf - from Gizmondo Studios Helsingborg/Atod AB games [Chicane Street Racing (Gizmondo), Fastlane Street Racing (iOS)] */
VGMSTREAM* init_vgmstream_lsf_n1nj4n(STREAMFILE *sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset, data_size, loop_start = 0, loop_end = 0;
int channels, loop_flag, sample_rate;
bool is_v2 = false;
/* checks */
if (!check_extensions(streamFile, "lsf"))
if ((read_u64be(0x00, sf) & 0xFFFFFFFFFFFFFF00) == get_id64be("!n1nj4n\0"))
is_v2 = false;
else if ((read_u64be(0x00, sf) & 0xFFFFFFFFFFFFFF00) == get_id64be("n1nj4n!\0"))
is_v2 = true; /* some files in Agaju: The Sacred Path (Gizmondo) */
else
return NULL;
/* .lsf: actual extension, exe strings seem to call this format "LSF" as well */
if (!check_extensions(sf, "lsf"))
return NULL;
uint8_t flags = read_u8(0x07, sf);
uint32_t offset = 0x08;
if (flags & 0x01) {
loop_start = read_u32le(offset + 0x00,sf);
loop_end = read_u32le(offset + 0x04,sf);
offset += 0x08;
}
if ((flags & 0x01) && (flags & 0x02)) {
//00: loop hist related?
offset += 0x04;
}
if (flags & 0x02) {
int count = read_u32le(offset + 0x00,sf); /* not channels */
// per entry:
// 00: channel related?
// 04: null?
// 0c: ~0x3130?
offset += 0x04 + 0x0c * count;
}
sample_rate = read_u32le(offset + 0x00, sf);
data_size = read_u32le(offset + 0x04, sf);
offset += 0x08;
start_offset = offset;
if (start_offset + data_size != get_streamfile_size(sf))
goto fail;
if (read_32bitBE(0x00, streamFile) != 0x216E316E || // "!n1n"
read_32bitBE(0x04, streamFile) != 0x6A346E00) // "j4n\0"
goto fail;
file_size = get_streamfile_size(streamFile);
if (read_32bitLE(0x0C, streamFile) + 0x10 != file_size)
goto fail;
loop_flag = 0;
channel_count = 1;
start_offset = 0x10;
channels = 1;
loop_flag = loop_end > 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_LSF_N1NJ4N;
vgmstream->sample_rate = read_32bitLE(0x08, streamFile);
vgmstream->num_samples = (file_size-0x10)/0x1c*0x1b*2;
vgmstream->coding_type = coding_LSF;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x1c;
vgmstream->sample_rate = sample_rate;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (is_v2) {
vgmstream->coding_type = coding_PSX_cfg;
vgmstream->layout_type = layout_none;
vgmstream->frame_size = 0x10;
}
else {
/* custom codec but basically obfuscted PSX-cfg */
vgmstream->coding_type = coding_LSF;
vgmstream->layout_type = layout_interleave; //TODO: flat but decoder doesn't handle it
vgmstream->interleave_block_size = 0x1c;
vgmstream->frame_size = 0x1c; /* fixed but used below */
}
vgmstream->num_samples = ps_cfg_bytes_to_samples(data_size, vgmstream->frame_size, channels);
vgmstream->loop_start_sample = ps_cfg_bytes_to_samples(loop_start, vgmstream->frame_size, channels);
vgmstream->loop_end_sample = ps_cfg_bytes_to_samples(loop_end, vgmstream->frame_size, channels);
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;

View File

@ -275,8 +275,6 @@ VGMSTREAM * init_vgmstream_xmu(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_xvas(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ngc_bh2pcm(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_sat_sap(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile);
@ -443,7 +441,7 @@ VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE* streamFile);
VGMSTREAM* init_vgmstream_smpl(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ps2_msa(STREAMFILE* streamFile);
VGMSTREAM* init_vgmstream_msa(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_voi(STREAMFILE* sf);
@ -615,7 +613,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_sk_aud(STREAMFILE * streamFile);
VGMSTREAM* init_vgmstream_stm(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_stma(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile);

View File

@ -34,8 +34,11 @@ VGMSTREAM* init_vgmstream_mpeg(STREAMFILE* sf) {
/* .mp3/mp2: standard
* .lmp3/lmp2: for plugins
* .mus: Marc Ecko's Getting Up (PC) */
if (!check_extensions(sf, "mp3,mp2,lmp3,lmp2,mus"))
* .mus: Marc Ecko's Getting Up (PC)
* .imf: Colors (Gizmondo)
* .aix: Classic Compendium 2 (Gizmondo)
* (extensionless): Interstellar Flames 2 (Gizmondo) */
if (!check_extensions(sf, "mp3,mp2,lmp3,lmp2,mus,imf,aix,,"))
goto fail;
loop_flag = 0;

62
src/meta/msa.c Normal file
View File

@ -0,0 +1,62 @@
#include "meta.h"
#include "../coding/coding.h"
/* MSA - from Sucess games [Psyvariar -Complete Edition- (PS2), Konohana Pack: 3tsu no Jikenbo (PS2)]*/
VGMSTREAM* init_vgmstream_msa(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset, data_size, channel_size, file_size;
int loop_flag, channels;
/* checks */
if (read_u32be(0x00,sf) != 0x00000000 || read_u32be(0x08,sf) != 0x00000000)
return NULL;
if (!check_extensions(sf, "msa"))
return NULL;
loop_flag = 0;
channels = 2;
start_offset = 0x14;
file_size = get_streamfile_size(sf);
data_size = read_u32le(0x04,sf); /* wrong, see below */
channel_size = read_u32le(0x0c,sf); /* also wrong like data_size */
if (!ps_check_format(sf, start_offset, 0x100))
return NULL;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_MSA;
vgmstream->sample_rate = read_s32le(0x10,sf);
if (vgmstream->sample_rate == 0) /* ex. Psyvariar's AME.MSA */
vgmstream->sample_rate = 44100;
vgmstream->num_samples = ps_bytes_to_samples(data_size, channels);
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
if (channel_size) /* Konohana Pack */
vgmstream->interleave_block_size = 0x6000;
else /* Psyvariar */
vgmstream->interleave_block_size = 0x4000;
/* MSAs are strangely truncated, so manually calculate samples.
* Data after last usable block is always silence or garbage. */
if (data_size > file_size) {
uint32_t usable_size = file_size - start_offset;
usable_size -= usable_size % (vgmstream->interleave_block_size * channels); /* block-aligned */
vgmstream->num_samples = ps_bytes_to_samples(usable_size, channels);
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,87 +0,0 @@
#include "meta.h"
#include "../util.h"
/* BH2PCM (from Bio Hazard 2) */
VGMSTREAM * init_vgmstream_ngc_bh2pcm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int channel_count;
int format_detect;
int loop_flag;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("bh2pcm",filename_extension(filename))) goto fail;
#if 0
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x00000000)
goto fail;
#endif
loop_flag = 0;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
format_detect=read_32bitLE(0x00,streamFile);
switch (format_detect) {
case 1:
start_offset = 0x20;
channel_count = 2;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 32000;
vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x04,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile);
}
break;
case 0:
start_offset = 0x20;
channel_count = 1;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 32000;
vgmstream->num_samples = read_32bitLE(0x0C,streamFile);
vgmstream->layout_type = layout_none;
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile);
vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile);
}
break;
default:
goto fail;
}
vgmstream->coding_type = coding_PCM16BE;
vgmstream->meta_type = meta_NGC_BH2PCM;
/* 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;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,63 +0,0 @@
#include "meta.h"
#include "../coding/coding.h"
/* MSA - from Sucess games [Psyvariar -Complete Edition- (PS2), Konohana Pack: 3tsu no Jikenbo (PS2)]*/
VGMSTREAM * init_vgmstream_ps2_msa(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
size_t data_size, channel_size, file_size;
/* checks */
if (!check_extensions(streamFile, "msa"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x00000000)
goto fail;
if (read_32bitBE(0x08,streamFile) != 0x00000000)
goto fail;
loop_flag = 0;
channel_count = 2;
start_offset = 0x14;
file_size = get_streamfile_size(streamFile);
data_size = read_32bitLE(0x04,streamFile); /* wrong, see below */
channel_size = read_32bitLE(0x0c,streamFile); /* also wrong like data_size */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_PS2_MSA;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
if (vgmstream->sample_rate == 0) /* ex. Psyvariar's AME.MSA */
vgmstream->sample_rate = 44100;
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
if (channel_size) /* Konohana Pack */
vgmstream->interleave_block_size = 0x6000;
else /* Psyvariar */
vgmstream->interleave_block_size = 0x4000;
/* (could also test first frame in various interleaves, as it's always 0'ed) */
/* MSAs are strangely truncated, so manually calculate samples.
* Data after last usable block is always silence or garbage. */
if (data_size > file_size) {
off_t usable_size = file_size - start_offset;
usable_size -= usable_size % (vgmstream->interleave_block_size*channel_count);/* block-aligned */
vgmstream->num_samples = ps_bytes_to_samples(usable_size, channel_count);//usable_size * 28 / (16*channel_count);
}
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -6,11 +6,10 @@
/* SEG - from Stormfront games [Eragon (multi), Forgotten Realms: Demon Stone (multi) */
VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
uint32_t start_offset, data_size;
int loop_flag, channels;
uint32_t codec;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
read_u32_t read_u32;
/* checks */
@ -19,19 +18,16 @@ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) {
if (!check_extensions(sf, "seg"))
goto fail;
codec = read_32bitBE(0x04,sf);
/* 0x08: version? (2: Eragon, Spiderwick Chronicles Wii / 3: Spiderwick Chronicles X360 / 4: Spiderwick Chronicles PC) */
if (guess_endian32(0x08,sf)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
}
codec = read_u32be(0x04,sf);
/* 0x08: version? (2: Eragon, Spiderwick Chronicles Wii / 3: Eragon X360, Spiderwick Chronicles X360 / 4: Spiderwick Chronicles PC) */
read_u32 = guess_read_u32(0x08, sf);
/* 0x0c: file size */
data_size = read_32bit(0x10, sf); /* including interleave padding */
data_size = read_u32(0x10, sf); /* including interleave padding */
/* 0x14: null */
loop_flag = read_32bit(0x20,sf); /* rare */
channel_count = read_32bit(0x24,sf);
loop_flag = read_u32(0x20,sf); /* rare */
channels = read_u32(0x24,sf);
/* 0x28: extradata 1 entries (0x08 per entry, unknown) */
/* 0x2c: extradata 1 offset */
/* 0x30: extradata 2 entries (0x10 or 0x14 per entry, seek/hist table?) */
@ -41,12 +37,12 @@ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) {
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SEG;
vgmstream->sample_rate = read_32bit(0x18,sf);
vgmstream->num_samples = read_32bit(0x1c,sf);
vgmstream->sample_rate = read_u32(0x18,sf);
vgmstream->num_samples = read_u32(0x1c,sf);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
@ -86,14 +82,29 @@ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x78623300: { /* "xb3\0" */
int block_size = 0x4000;
/* no apparent flag */
if (read_u32be(start_offset, sf) == 0) {
/* Eragon (PC) */
start_offset += 0x20A; /* one frame */
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
mpeg_custom_config cfg = {0};
vgmstream->codec_data = init_mpeg_custom(sf, start_offset, &vgmstream->coding_type, channels, MPEG_STANDARD, &cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none;
}
else {
/* The Spiderwick Chronicles (X360) */
int block_size = 0x4000;
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0); /* samples are ok */
}
xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0); /* samples are ok */
break;
}
#endif

View File

@ -2,7 +2,7 @@
#include "../coding/coding.h"
/* STM - from Angel Studios/Rockstar San Diego games [Red Dead Revolver (PS2), Spy Hunter 2 (PS2/Xbox)] */
VGMSTREAM* init_vgmstream_stm(STREAMFILE* sf) {
VGMSTREAM* init_vgmstream_stma(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag = 0, channel_count;
@ -65,7 +65,7 @@ VGMSTREAM* init_vgmstream_stm(STREAMFILE* sf) {
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bit(0xc,sf);
vgmstream->meta_type = meta_STM;
vgmstream->meta_type = meta_STMA;
vgmstream->layout_type = (channel_count > 1) ? layout_interleave : layout_none;
switch(bps) {
@ -109,7 +109,7 @@ VGMSTREAM* init_vgmstream_stm(STREAMFILE* sf) {
}
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

View File

@ -3,6 +3,7 @@
#include "../streamfile.h"
#include "reader_get.h"
#include "reader_sf.h"
typedef uint32_t (*read_u32_t)(off_t, STREAMFILE*);
typedef int32_t (*read_s32_t)(off_t, STREAMFILE*);
@ -25,4 +26,8 @@ static inline int guess_endian32(off_t offset, STREAMFILE* sf) {
return get_u32le(buf) > get_u32be(buf) ? 1 : 0;
}
static inline read_u32_t guess_read_u32(off_t offset, STREAMFILE* sf) {
return guess_endian32(0x08,sf) ? read_u32be : read_u32le;
}
#endif

View File

@ -115,7 +115,6 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_dc_str_v2,
init_vgmstream_xmu,
init_vgmstream_xvas,
init_vgmstream_ngc_bh2pcm,
init_vgmstream_sat_sap,
init_vgmstream_dc_idvi,
init_vgmstream_ps2_rnd,
@ -206,7 +205,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_bnsf,
init_vgmstream_ps2_gcm,
init_vgmstream_smpl,
init_vgmstream_ps2_msa,
init_vgmstream_msa,
init_vgmstream_voi,
init_vgmstream_ngc_rkv,
init_vgmstream_dsp_ddsp,
@ -305,7 +304,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_ea_mpf_mus,
init_vgmstream_ea_schl_fixed,
init_vgmstream_sk_aud,
init_vgmstream_stm,
init_vgmstream_stma,
init_vgmstream_ea_snu,
init_vgmstream_awc,
init_vgmstream_opus_std,
@ -1149,13 +1148,6 @@ int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_o
return 1;
#endif
if ((vgmstream->coding_type == coding_PSX_cfg ||
vgmstream->coding_type == coding_PSX_pivotal) &&
(vgmstream->interleave_block_size == 0 || vgmstream->interleave_block_size > 0x50)) {
VGM_LOG("VGMSTREAM: PSX-cfg decoder with wrong frame size %x\n", vgmstream->interleave_block_size);
goto fail;
}
if ((vgmstream->coding_type == coding_CRI_ADX ||
vgmstream->coding_type == coding_CRI_ADX_enc_8 ||
vgmstream->coding_type == coding_CRI_ADX_enc_9 ||
@ -1168,16 +1160,24 @@ int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_o
if ((vgmstream->coding_type == coding_MSADPCM || vgmstream->coding_type == coding_MSADPCM_ck ||
vgmstream->coding_type == coding_MSADPCM_int ||
vgmstream->coding_type == coding_MS_IMA || vgmstream->coding_type == coding_MS_IMA_mono
vgmstream->coding_type == coding_MS_IMA || vgmstream->coding_type == coding_MS_IMA_mono ||
vgmstream->coding_type == coding_PSX_cfg || vgmstream->coding_type == coding_PSX_pivotal
) &&
vgmstream->frame_size == 0) {
vgmstream->frame_size = vgmstream->interleave_block_size;
}
if ((vgmstream->coding_type == coding_PSX_cfg ||
vgmstream->coding_type == coding_PSX_pivotal) &&
(vgmstream->frame_size == 0 || vgmstream->frame_size > 0x50)) {
VGM_LOG("VGMSTREAM: PSX-cfg decoder with wrong frame size %x\n", vgmstream->frame_size);
goto fail;
}
if ((vgmstream->coding_type == coding_MSADPCM ||
vgmstream->coding_type == coding_MSADPCM_ck ||
vgmstream->coding_type == coding_MSADPCM_int) &&
(vgmstream->frame_size > MSADPCM_MAX_BLOCK_SIZE)) {
(vgmstream->frame_size == 0 || vgmstream->frame_size > MSADPCM_MAX_BLOCK_SIZE)) {
VGM_LOG("VGMSTREAM: MSADPCM decoder with wrong frame size %x\n", vgmstream->frame_size);
goto fail;
}

View File

@ -348,7 +348,6 @@ typedef enum {
meta_NGC_TYDSP, /* Ty - The Tasmanian Tiger */
meta_DC_STR, /* SEGA Stream Asset Builder */
meta_DC_STR_V2, /* variant of SEGA Stream Asset Builder */
meta_NGC_BH2PCM, /* Bio Hazard 2 */
meta_SAP,
meta_DC_IDVI, /* Eldorado Gate */
meta_KRAW, /* Geometry Wars - Galaxies */
@ -461,7 +460,7 @@ typedef enum {
meta_SSS, /* raw Siren 14, 48kbit stereo */
meta_PS2_GCM, /* NamCollection */
meta_SMPL,
meta_PS2_MSA, /* Psyvariar -Complete Edition- */
meta_MSA,
meta_VOI,
meta_P3D, /* Prototype P3D */
meta_NGC_RKV, /* Legacy of Kain - Blood Omen 2 (GC) */
@ -544,7 +543,7 @@ typedef enum {
meta_TXTH, /* generic text header */
meta_SK_AUD, /* Silicon Knights .AUD (Eternal Darkness GC) */
meta_AHX,
meta_STM, /* Angel Studios/Rockstar San Diego Games */
meta_STMA,
meta_BINK, /* RAD Game Tools BINK audio/video */
meta_EA_SNU, /* Electronic Arts SNU (Dead Space) */
meta_AWC, /* Rockstar AWC (GTA5, RDR) */