mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-19 00:04:04 +01:00
cleanup
- use LF instead of CRLF - follow common name and code conventions used in other meta - reduce comment verbosity (should mainly comment unusual points or ) - should declare variables at block level - skip some checks that are unlikely to matter - read stream name
This commit is contained in:
parent
82ee723a19
commit
887af76ef6
@ -1157,7 +1157,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_PS2_WB, "Shooting Love. ~TRIZEAL~ WB header"},
|
||||
{meta_S14, "Namco .S14 raw header"},
|
||||
{meta_SSS, "Namco .SSS raw header"},
|
||||
{meta_PS2_GCM, "GCM 'MCG' Header"},
|
||||
{meta_PS2_GCM, "Namco GCM header"},
|
||||
{meta_PS2_SMPL, "Homura SMPL header"},
|
||||
{meta_PS2_MSA, "Success .MSA header"},
|
||||
{meta_NGC_PDT, "Hudson .PDT header"},
|
||||
|
@ -1,125 +1,78 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* .GCM - from select Namco games released in around the PS2 era [Gunvari Collection + Time Crisis (PS2), NamCollection (PS2)] */
|
||||
VGMSTREAM* init_vgmstream_ps2_gcm(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
|
||||
uint32_t vagp_l_offset, vagp_r_offset, gcm_samples, data_size, gcm_sample_rate, gcm_channels;
|
||||
|
||||
/* checks */
|
||||
/* .gcm: actual extension. */
|
||||
if (!check_extensions(sf, "gcm"))
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_u32be(0x00,sf) != 0x4D434700) /* "MCG" */
|
||||
goto fail;
|
||||
|
||||
/* GCM format as Namco outlined it is a hacked VAGp stereo format that can hold 6-channel audio at will.
|
||||
* so, first step is to deal with whatever quirks the format might have. */
|
||||
vagp_l_offset = read_u32le(0x04, sf); /* "left" VAGp header pointer. */
|
||||
if (vagp_l_offset != 0x20)
|
||||
goto fail;
|
||||
vagp_r_offset = read_u32le(0x08, sf); /* "right" VAGp header pointer. */
|
||||
if (vagp_r_offset != 0x50)
|
||||
goto fail;
|
||||
start_offset = read_u32le(0x0c, sf); /* raw "stereo VAG" data pointer. */
|
||||
if (start_offset != 0x80)
|
||||
goto fail;
|
||||
gcm_samples = read_u32le(0x10, sf); /* size of raw "stereo VAG" data, not exactly correct for multi-channel files as we'll see below. */
|
||||
|
||||
/* second step is to check actual GCM size and decide the "channels" value from there.
|
||||
* not helping matters is there's nothing in the GCM header that indicates whether or not this GCM is actually multi-channel in any way.
|
||||
* meaning we have to manually support those Klonoa multi-channel files (KLN3182M.GCM, KLN3191M.GCM, etc). */
|
||||
data_size = get_streamfile_size(sf) - start_offset;
|
||||
if (data_size == (gcm_samples * 3)) {
|
||||
/* 6-channel GCM file. */
|
||||
gcm_channels = 6;
|
||||
}
|
||||
else if (data_size == gcm_samples) {
|
||||
/* stereo GCM file. */
|
||||
gcm_channels = 2;
|
||||
}
|
||||
else {
|
||||
/* there is only one known GCM "multi-channel" setup and it's hacky. */
|
||||
goto fail;
|
||||
}
|
||||
/* what follows are two VAGp headers and raw data, third and final step is to perform sanity checks on them (except the data itself) and go from there. */
|
||||
|
||||
/* VAGp signature field, always present. */
|
||||
uint32_t vagp_l_sig, vagp_r_sig, vagp_sig;
|
||||
vagp_l_sig = read_u32be(vagp_l_offset, sf);
|
||||
vagp_r_sig = read_u32be(vagp_r_offset, sf);
|
||||
if (vagp_l_sig != vagp_r_sig) {
|
||||
/* check two identical values against each other. */
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
/* check for "VAGp" value. */
|
||||
vagp_sig = vagp_r_sig;
|
||||
if (vagp_sig != 0x56414770) goto fail; /* "VAGp" */
|
||||
}
|
||||
/* VAGp version field, always 4. */
|
||||
uint32_t vagp_l_ver, vagp_r_ver, vagp_ver;
|
||||
vagp_l_ver = read_u32be(vagp_l_offset + 4, sf);
|
||||
vagp_r_ver = read_u32be(vagp_r_offset + 4, sf);
|
||||
if (vagp_l_ver != vagp_r_ver) {
|
||||
/* check two identical values against each other. */
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
/* check for "version 4" value. */
|
||||
vagp_ver = vagp_r_ver;
|
||||
if (vagp_ver != 4) goto fail;
|
||||
}
|
||||
/* VAGp size field, usually separate per channel and does not cover blank frames at all. */
|
||||
uint32_t vagp_l_size, vagp_r_size, vagp_samples;
|
||||
vagp_l_size = read_u32be(vagp_l_offset + 12, sf);
|
||||
vagp_r_size = read_u32be(vagp_r_offset + 12, sf);
|
||||
if (vagp_l_size != vagp_r_size) {
|
||||
/* check two identical values against each other. */
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
/* assign one of the two existing "vag size" values to an entirely new "vag size" variable to be used later. */
|
||||
vagp_samples = vagp_r_size;
|
||||
}
|
||||
/* VAGp sample rate field, usually separate per channel. */
|
||||
uint32_t vagp_l_sample_rate, vagp_r_sample_rate;
|
||||
vagp_l_sample_rate = read_u32be(vagp_l_offset + 16, sf);
|
||||
vagp_r_sample_rate = read_u32be(vagp_r_offset + 16, sf);
|
||||
if (vagp_l_sample_rate != vagp_r_sample_rate) {
|
||||
/* check two identical values against each other. */
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
/* assign one of the two existing "sample rate" values to an entirely new "sample rate" variable to be used later. */
|
||||
gcm_sample_rate = vagp_r_sample_rate;
|
||||
}
|
||||
|
||||
/* build the VGMSTREAM by allocating it to total number of channels and a single loop flag.
|
||||
* though loop flag is set to 0. GCM files don't really "loop" by themselves. */
|
||||
vgmstream = allocate_vgmstream(gcm_channels,0);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics. */
|
||||
vgmstream->meta_type = meta_PS2_GCM;
|
||||
vgmstream->sample_rate = gcm_sample_rate;
|
||||
vgmstream->num_samples = ps_bytes_to_samples(vagp_samples, 1);
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_u32le(0x14, sf);
|
||||
|
||||
/* open the file for reading. */
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened. */
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* .GCM - from PS2 Namco games [Gunvari Collection + Time Crisis (PS2), NamCollection (PS2)] */
|
||||
VGMSTREAM* init_vgmstream_ps2_gcm(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
uint32_t start_offset, name_offset;
|
||||
uint32_t vagp_l_offset, vagp_r_offset, track_size, data_size, channel_size;
|
||||
int channels, sample_rate, interleave;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "MCG\0"))
|
||||
goto fail;
|
||||
|
||||
/* .gcm: actual extension */
|
||||
if (!check_extensions(sf, "gcm"))
|
||||
goto fail;
|
||||
|
||||
|
||||
/* format is two v4 "VAGp" headers then interleaved data (even for 6ch files) */
|
||||
vagp_l_offset = read_u32le(0x04, sf);
|
||||
if (!is_id32be(vagp_l_offset,sf, "VAGp"))
|
||||
goto fail;
|
||||
vagp_r_offset = read_u32le(0x08, sf);
|
||||
if (!is_id32be(vagp_r_offset,sf, "VAGp"))
|
||||
goto fail;
|
||||
|
||||
start_offset = read_u32le(0x0c, sf);
|
||||
track_size = read_u32le(0x10, sf); /* stereo size */
|
||||
interleave = read_s32le(0x14, sf);
|
||||
/* 0x18/1c: null */
|
||||
|
||||
/* nothing in the header indicates multi-channel files (*M.GCM), check expected sizes of stereo pairs */
|
||||
data_size = get_streamfile_size(sf) - start_offset;
|
||||
if (data_size == (track_size * 3)) {
|
||||
channels = 6;
|
||||
}
|
||||
else if (data_size == track_size) {
|
||||
channels = 2;
|
||||
}
|
||||
else {
|
||||
goto fail; /* unknown setup (could also check start frames are null) */
|
||||
}
|
||||
|
||||
/* get some values from the VAGp */
|
||||
channel_size = read_u32be(vagp_l_offset + 0x0c, sf); /* without padding */
|
||||
sample_rate = read_s32be(vagp_l_offset + 0x10, sf);
|
||||
name_offset = vagp_l_offset + 0x20; /* both VAGp use the same name (sometimes with an L/R letter) */
|
||||
|
||||
if (channel_size != read_u32be(vagp_r_offset + 0x0c, sf)) /* unlikely... */
|
||||
goto fail;
|
||||
if (sample_rate != read_u32be(vagp_r_offset + 0x10, sf)) /* unlikely.. */
|
||||
goto fail;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, 0);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_PS2_GCM;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = ps_bytes_to_samples(channel_size, 1);
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
|
||||
read_string(vgmstream->stream_name,0x10+1, name_offset,sf);
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user