Merge pull request #1312 from bnnm/etc-fixes

- Fix MSVC Winamp text/path issues
- Fix .fsbkey
- Add FSB keys
- Fix seek to 0 in non-libopus Opus
- Cleanup
This commit is contained in:
bnnm 2023-02-17 01:15:09 +01:00 committed by GitHub
commit 87034988dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 309 additions and 254 deletions

30
.github/uploader.py vendored
View File

@ -22,6 +22,8 @@ import urllib.request, json, argparse, glob, subprocess, os
#
# API: https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28
# https://docs.github.com/en/rest/releases/assets?apiVersion=2022-11-28
#
# Github's API has some limits but hopefully not reached by current token
RELEASE_TAG = 'nightly'
# gives info about release (public)
@ -32,6 +34,8 @@ URL_DELETE = 'https://api.github.com/repos/vgmstream/vgmstream-releases/releases
URL_UPLOAD = 'https://uploads.github.com/repos/vgmstream/vgmstream-releases/releases/%s/assets?name=%s'
# change release info
URL_UPDATE = 'https://api.github.com/repos/vgmstream/vgmstream-releases/releases/%s'
# gives info about last vgmstream tag
URL_VGMSTREAM = 'https://api.github.com/repos/vgmstream/vgmstream/releases?per_page=1'
#------------------------------------------------------------------------------
@ -40,6 +44,12 @@ def get_release():
data = json.loads(contents)
return data
def get_vgmstream_tag():
# TODO could use local git tag
contents = urllib.request.urlopen(URL_VGMSTREAM).read()
data = json.loads(contents)
return data[0]['tag_name']
def update_release(release, token, debug, body):
release_id = release['id']
@ -117,7 +127,7 @@ def generate_changelog(release, token, debug):
# writes in work dir and gets lines
lines = changelog.main()
current_tag = 'r1810' #TODO get from some API maybe
current_tag = get_vgmstream_tag()
body = [
'Automated releases ([full diffs here](https://github.com/vgmstream/vgmstream/compare/%s...master)).' % (current_tag),
'',
@ -159,17 +169,27 @@ def main(args):
#if not files:
# raise ValueError("no files found")
# shouldn't happen (points to non-existing files)
if args.files and not files:
raise ValueError("no files found, expected: %s" % (args.files))
# this token usually only exists in env on merges, but allow passing for tests
token = args.token
if not token:
token = os.environ.get('UPLOADER_GITHUB_TOKEN')
if not token:
print("token not defined")
raise ValueError("token not defined")
release = get_release()
for file in files:
delete_asset(release, token, args.debug, file)
upload_asset(release, token, args.debug, file)
print("handling %s files" % (len(files)))
try:
release = get_release()
for file in files:
delete_asset(release, token, args.debug, file)
upload_asset(release, token, args.debug, file)
except Exception as e:
print("error during process: %s" % (e))
raise ValueError("could't upload")
# this should be invoked separately so release doesn't change per artifact
if args.changelog:

View File

@ -65,6 +65,7 @@ jobs:
# uploads current assets to vgmstream-releases (token only works on merges)
- name: Upload artifacts to vgmstream-releases
if: github.event_name != 'pull_request'
shell: cmd
working-directory: ${{github.workspace}}
env:
UPLOADER_GITHUB_TOKEN: ${{ secrets.UPLOADER_GITHUB_TOKEN }}

View File

@ -63,6 +63,7 @@ def parse_args():
ap.add_argument("-cn","--cli-new", help="sets name of new CLI (can be a path)")
ap.add_argument("-co","--cli-old", help="sets name of old CLI (can be a path)")
ap.add_argument("-m","--multiprocesses", help="uses N multiprocesses to compare for performance\n(note that pypy w/ single process is faster than multiprocesses)", type=int, default=1)
ap.add_argument("-d","--diffs", help="compares input files directly (won't decode)", action='store_true')
args = ap.parse_args()
@ -385,10 +386,11 @@ class VrtsFiles:
if not os.path.isfile(file):
continue
# ignores non useful files
_, ext = os.path.splitext(file)
if ext.lower() in IGNORED_EXTENSIONS:
continue
# ignores non useful files, except on diffs mode that uses them directly
if not self._args.diffs:
_, ext = os.path.splitext(file)
if ext.lower() in IGNORED_EXTENSIONS:
continue
self.filenames.append(file)
@ -497,6 +499,9 @@ class VrtsApp:
# - can be passed a dir or file for old/new
# - old is optional in performance mode
def _detect_cli(self):
if self._args.diffs:
return
cli = self._find_cli(self._args.cli_new, DEFAULT_CLI_NEW)
if cli:
self._cli_new = cli
@ -626,10 +631,28 @@ class VrtsApp:
pass
self._temp_files = []
def _diffs(self):
files = self._files.filenames
print(files)
for i in range(len(files) - 1):
curr = files[i]
next = files[i+1]
print(curr, next)
fuzzy = self._args.fuzzy
cmp = VrtsComparator(curr, next, fuzzy_max=fuzzy, concurrency=self._args.multiprocesses)
code = cmp.compare()
self._p.result(curr, code)
def start(self):
self._detect_cli()
self._files.prepare()
if self._args.performance:
if self._args.diffs:
self._diffs()
elif self._args.performance:
self._performance()
else:
self._compare()

View File

@ -778,10 +778,16 @@ static ffmpeg_codec_data* init_ffmpeg_custom_opus_config(STREAMFILE* sf, off_t s
ffmpeg_data = init_ffmpeg_offset(temp_sf, 0x00, get_streamfile_size(temp_sf));
if (!ffmpeg_data) goto fail;
/* FFmpeg + libopus: skips samples, notifies skip in codecCtx->delay (not in stream->skip_samples)
* FFmpeg + opus: *doesn't* skip, also notifies skip in codecCtx->delay, hurray (possibly fixed in recent versions)
* FFmpeg + opus is audibly buggy with some low bitrate SSB Ultimate files */
//ffmpeg_set_skip_samples(ffmpeg_data, skip);
/* FFmpeg + libopus: skips samples, notifies skip in codecCtx->delay/initial_padding (not in stream->skip_samples)
* FFmpeg + opus: skip samples but loses them on reset/seek to 0, also notifies skip in codecCtx->delay/initial_padding */
{
/* quick fix for non-libopus (not sure how to detect better since both share AV_CODEC_ID_OPUS)*/
const char* name = ffmpeg_get_codec_name(ffmpeg_data);
if (name && (name[0] == 'O' || name[0] == 'o')) { /* "Opus" vs "libopus" */
//ffmpeg_set_skip_samples(ffmpeg_data, cfg->skip); /* can't overwrite internal decoder skip */
ffmpeg_set_force_seek(ffmpeg_data);
}
}
close_streamfile(temp_sf);
return ffmpeg_data;

View File

@ -25,7 +25,10 @@ VGMSTREAM* init_vgmstream_fsb_encrypted(STREAMFILE* sf) {
uint8_t key[FSB_KEY_MAX];
size_t key_size = read_key_file(key, FSB_KEY_MAX, sf);
test_fsbkey(sf, key, key_size, MODE_FSBS_ALL);
if (key_size) {
vgmstream = test_fsbkey(sf, key, key_size, MODE_FSBS_ALL);
return vgmstream;
}
}
@ -65,22 +68,22 @@ static VGMSTREAM* test_fsbkey(STREAMFILE* sf, const uint8_t* key, size_t key_siz
if (!vc && test_std) {
temp_sf = setup_fsb_streamfile(sf, key, key_size, 0);
if (!temp_sf) return NULL;
//;dump_streamfile(temp_sf, 0);
if (!vc && test_fsb4) vc = init_vgmstream_fsb(temp_sf);
if (!vc && test_fsb5) vc = init_vgmstream_fsb5(temp_sf);
//;if (vgmstream) dump_streamfile(temp_sf, 0);
close_streamfile(temp_sf);
}
if (!vc && test_alt) {
temp_sf = setup_fsb_streamfile(sf, key, key_size, 1);
if (!temp_sf) return NULL;
//;dump_streamfile(temp_sf, 1);
if (!vc && test_fsb4) vc = init_vgmstream_fsb(temp_sf);
if (!vc && test_fsb5) vc = init_vgmstream_fsb5(temp_sf);
//;if (vgmstream) dump_streamfile(temp_sf, 0);
close_streamfile(temp_sf);
}

View File

@ -68,7 +68,8 @@ static const fsbkey_info fsbkey_list[] = {
{ MODE_FSB5_STD, FSBKEY_ADD("4FB8CC894515617939F4E1B7D50972D27213B8E6") }, // Cult of the Lamb Demo (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("X3EK%Bbga-%Y9HZZ%gkc*C512*$$DhRxWTGgjUG@=rUD") }, // Signalis (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("281ad163160cfc16f9a22c6755a64fad") }, // Ash Echoes beta (Android)
{ MODE_FSB5_STD, FSBKEY_ADD("Aurogon666") }, // Afterimage demo (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("IfYouLikeThosesSoundsWhyNotRenumerateTheir2Authors?") }, // Blanc (PC/Switch)
};
static const int fsbkey_list_count = sizeof(fsbkey_list) / sizeof(fsbkey_list[0]);

View File

@ -1,234 +1,235 @@
#include "meta.h"
#include "../coding/coding.h"
/* RFTM - Retro Studios format [Metroid Prime Remastered] */
VGMSTREAM *init_vgmstream_rfrm_mpr(STREAMFILE *streamFile) {
VGMSTREAM *vgmstream = NULL;
off_t fmta_offset = 0, data_offset = 0, ras3_offset = 0, header_offset, start_offset;
size_t data_size = 0, interleave;
int loop_flag, channel_count;
int loop_start, loop_end, padding;
/* checks */
if (!check_extensions(streamFile, "csmp"))
goto fail;
if (read_32bitBE(0x00, streamFile) != 0x5246524D) /* "RFRM" */
goto fail;
/* 0x08: file size but not exact */
if (read_32bitBE(0x14, streamFile) != 0x43534D50) /* "CSMP" */
goto fail;
if (read_32bitLE(0x18,streamFile) != 0x1F) /* assumed, also at 0x1c */
goto fail;
/* parse chunks (always BE) */
{
off_t chunk_offset = 0x20;
off_t file_size = get_streamfile_size(streamFile);
while (chunk_offset < file_size) {
uint32_t chunk_type = read_32bitBE(chunk_offset + 0x00,streamFile);
size_t chunk_size = read_32bitLE(chunk_offset + 0x08,streamFile);
switch(chunk_type) {
case 0x464D5441: /* "FMTA" */
fmta_offset = chunk_offset + 0x18;
chunk_offset += 5 + 0x18 + chunk_size;
break;
case 0x44415441: /* "DATA" */
data_offset = chunk_offset + 0x18;
data_size = read_32bitLE(chunk_offset + 0x04, streamFile);
/* we're done here, DATA is the last chunk */
chunk_offset = file_size;
break;
case 0x52415333: /* "RAS3" */
ras3_offset = chunk_offset + 0x18;
chunk_offset += 60;
break;
case 0x43524D53: /* CRMS */
chunk_offset += 9 + 0x18 + chunk_size + read_32bitLE(chunk_offset + 0x18 + chunk_size + 5, streamFile);
break;
default:
goto fail;
}
}
if (!fmta_offset || !data_offset || !data_size)
goto fail;
}
/* parse FMTA / DATA (fully interleaved standard DSPs) */
channel_count = read_8bit(fmta_offset + 0x00, streamFile);
/* FMTA 0x08: channel mapping */
header_offset = data_offset;
start_offset = header_offset + 0x80 * channel_count;
loop_flag = read_16bitLE(header_offset + 0x0C, streamFile);
interleave = data_size / channel_count;
if (ras3_offset) {
int block_size = read_32bitLE(ras3_offset + 0x00, streamFile);
int block_samples = read_32bitLE(ras3_offset + 0x8, streamFile);
int loop_start_block = read_32bitLE(ras3_offset + 0x14, streamFile);
int loop_start_sample = read_32bitLE(ras3_offset + 0x18, streamFile);
int loop_end_block = read_32bitLE(ras3_offset + 0x1C, streamFile);
int loop_end_sample = read_32bitLE(ras3_offset + 0x20, streamFile);
padding = read_32bitLE(ras3_offset + 0x0C, streamFile);
loop_start = loop_start_block * block_samples + loop_start_sample - padding;
loop_end = loop_end_block * block_samples + loop_end_sample - padding;
if ((loop_start || loop_end) && (loop_start < loop_end))
loop_flag = 1;
interleave = block_size / channel_count;
} else {
loop_start = dsp_nibbles_to_samples(read_32bitLE(header_offset + 0x10, streamFile));
loop_end = dsp_nibbles_to_samples(read_32bitLE(header_offset + 0x14, streamFile)) + 1;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_RFRM;
vgmstream->sample_rate = read_32bitLE(header_offset + 0x08, streamFile);
vgmstream->num_samples = read_32bitLE(header_offset + 0x00, streamFile);
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */
vgmstream->loop_end_sample = vgmstream->num_samples;
if (ras3_offset) {
int padding_bytes = padding / 14 * 8; /* round to frames */
vgmstream->interleave_first_block_size = interleave - padding_bytes;
vgmstream->interleave_first_skip = padding_bytes;
start_offset += padding_bytes;
}
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
dsp_read_coefs(vgmstream, streamFile, header_offset + 0x1C, 0x80, 0);
dsp_read_hist (vgmstream, streamFile, header_offset + 0x40, 0x80, 0);
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
/* RFTM - Retro Studios format [Donkey Kong Country Tropical Freeze (WiiU/Switch)] */
VGMSTREAM *init_vgmstream_rfrm(STREAMFILE *streamFile) {
VGMSTREAM *vgmstream = NULL;
off_t fmta_offset = 0, data_offset = 0, header_offset, start_offset;
size_t data_size = 0, interleave;
int loop_flag, channel_count, version;
int big_endian;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
/* checks */
if (!check_extensions(streamFile, "csmp"))
goto fail;
if (read_32bitBE(0x00, streamFile) != 0x5246524D) /* "RFRM" */
goto fail;
/* 0x08: file size but not exact */
if (read_32bitBE(0x14, streamFile) != 0x43534D50) /* "CSMP" */
goto fail;
version = read_32bitBE(0x18,streamFile); /* assumed, also at 0x1c */
if (version == 0x0a) { /* Wii U */
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
big_endian = 1;
}
else if (version == 0x12) { /* Switch */
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
big_endian = 0;
}
else if (version == 0x1F000000) { /* Metroid Prime Remastered */
return init_vgmstream_rfrm_mpr(streamFile);
}
else {
goto fail;
}
/* parse chunks (always BE) */
{
off_t chunk_offset = 0x20;
off_t file_size = get_streamfile_size(streamFile);
while (chunk_offset < file_size) {
uint32_t chunk_type = read_32bitBE(chunk_offset+0x00,streamFile);
size_t chunk_size = read_32bitBE(chunk_offset+0x08,streamFile); /* maybe 64b from 0x04? */
switch(chunk_type) {
case 0x464D5441: /* "FMTA" */
fmta_offset = chunk_offset + 0x18;
break;
case 0x44415441: /* "DATA" */
data_offset = chunk_offset + 0x18;
data_size = chunk_size;
break;
default: /* known: "LABL" (usually before "FMTA"), "META" (usually after "DATA") */
break;
}
chunk_offset += 0x18 + chunk_size;
}
if (!fmta_offset || !data_offset || !data_size)
goto fail;
}
/* parse FMTA / DATA (fully interleaved standard DSPs) */
channel_count = read_8bit(fmta_offset+0x00, streamFile);
/* FMTA 0x08: channel mapping */
header_offset = data_offset;
if (version == 0x0a) {
size_t align = 0x03; /* possibly 32b align */
header_offset += align;
data_size -= align;
}
start_offset = header_offset + 0x60;
loop_flag = read_16bit(header_offset + 0x0C, streamFile);
interleave = data_size / channel_count;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_RFRM;
vgmstream->sample_rate = read_32bit(header_offset + 0x08, streamFile);
vgmstream->num_samples = read_32bit(header_offset + 0x00, streamFile);
vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bit(header_offset + 0x10, streamFile));
vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bit(header_offset + 0x14, streamFile)) + 1;
if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
dsp_read_coefs(vgmstream, streamFile, header_offset + 0x1C, interleave, big_endian);
dsp_read_hist (vgmstream, streamFile, header_offset + 0x40, interleave, big_endian);
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
#include "meta.h"
#include "../coding/coding.h"
/* RFTM - Retro Studios format [Metroid Prime Remastered] */
static VGMSTREAM* init_vgmstream_rfrm_mpr(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t fmta_offset = 0, data_offset = 0, ras3_offset = 0, header_offset, start_offset;
size_t data_size = 0, interleave;
int loop_flag, channels;
int loop_start, loop_end, padding;
/* checks */
if (!is_id32be(0x00, sf, "RFRM"))
goto fail;
/* 0x08: file size but not exact */
if (!is_id32be(0x14, sf, "CSMP"))
goto fail;
if (!check_extensions(sf, "csmp"))
goto fail;
if (read_32bitLE(0x18,sf) != 0x1F) /* assumed, also at 0x1c */
goto fail;
/* parse chunks (always BE) */
{
off_t chunk_offset = 0x20;
off_t file_size = get_streamfile_size(sf);
while (chunk_offset < file_size) {
uint32_t chunk_type = read_32bitBE(chunk_offset + 0x00,sf);
size_t chunk_size = read_32bitLE(chunk_offset + 0x08,sf);
switch(chunk_type) {
case 0x464D5441: /* "FMTA" */
fmta_offset = chunk_offset + 0x18;
chunk_offset += 5 + 0x18 + chunk_size;
break;
case 0x44415441: /* "DATA" */
data_offset = chunk_offset + 0x18;
data_size = read_32bitLE(chunk_offset + 0x04, sf);
/* we're done here, DATA is the last chunk */
chunk_offset = file_size;
break;
case 0x52415333: /* "RAS3" */
ras3_offset = chunk_offset + 0x18;
chunk_offset += 60;
break;
case 0x43524D53: /* CRMS */
chunk_offset += 9 + 0x18 + chunk_size + read_32bitLE(chunk_offset + 0x18 + chunk_size + 5, sf);
break;
default:
goto fail;
}
}
if (!fmta_offset || !data_offset || !data_size)
goto fail;
}
/* parse FMTA / DATA (fully interleaved standard DSPs) */
channels = read_8bit(fmta_offset + 0x00, sf);
if (channels == 0) goto fail; /* div by zero */
/* FMTA 0x08: channel mapping */
header_offset = data_offset;
start_offset = header_offset + 0x80 * channels;
loop_flag = read_16bitLE(header_offset + 0x0C, sf);
interleave = data_size / channels;
if (ras3_offset) {
int block_size = read_32bitLE(ras3_offset + 0x00, sf);
int block_samples = read_32bitLE(ras3_offset + 0x8, sf);
int loop_start_block = read_32bitLE(ras3_offset + 0x14, sf);
int loop_start_sample = read_32bitLE(ras3_offset + 0x18, sf);
int loop_end_block = read_32bitLE(ras3_offset + 0x1C, sf);
int loop_end_sample = read_32bitLE(ras3_offset + 0x20, sf);
padding = read_32bitLE(ras3_offset + 0x0C, sf);
loop_start = loop_start_block * block_samples + loop_start_sample - padding;
loop_end = loop_end_block * block_samples + loop_end_sample - padding;
if ((loop_start || loop_end) && (loop_start < loop_end))
loop_flag = 1;
interleave = block_size / channels;
} else {
loop_start = dsp_nibbles_to_samples(read_32bitLE(header_offset + 0x10, sf));
loop_end = dsp_nibbles_to_samples(read_32bitLE(header_offset + 0x14, sf)) + 1;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_RFRM;
vgmstream->sample_rate = read_32bitLE(header_offset + 0x08, sf);
vgmstream->num_samples = read_32bitLE(header_offset + 0x00, sf);
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */
vgmstream->loop_end_sample = vgmstream->num_samples;
if (ras3_offset) {
int padding_bytes = padding / 14 * 8; /* round to frames */
vgmstream->interleave_first_block_size = interleave - padding_bytes;
vgmstream->interleave_first_skip = padding_bytes;
start_offset += padding_bytes;
}
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
dsp_read_coefs(vgmstream, sf, header_offset + 0x1C, 0x80, 0);
dsp_read_hist (vgmstream, sf, header_offset + 0x40, 0x80, 0);
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
/* RFTM - Retro Studios format [Donkey Kong Country Tropical Freeze (WiiU/Switch)] */
VGMSTREAM* init_vgmstream_rfrm(STREAMFILE* sf) {
VGMSTREAM *vgmstream = NULL;
off_t fmta_offset = 0, data_offset = 0, header_offset, start_offset;
size_t data_size = 0, interleave;
int loop_flag, channels, version;
int big_endian;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
/* checks */
if (!is_id32be(0x00, sf, "RFRM"))
goto fail;
/* 0x08: file size but not exact */
if (!is_id32be(0x14, sf, "CSMP"))
goto fail;
if (!check_extensions(sf, "csmp"))
goto fail;
version = read_32bitBE(0x18,sf); /* assumed, also at 0x1c */
if (version == 0x0a) { /* Wii U */
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
big_endian = 1;
}
else if (version == 0x12) { /* Switch */
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
big_endian = 0;
}
else if (version == 0x1F000000) { /* Metroid Prime Remastered */
return init_vgmstream_rfrm_mpr(sf);
}
else {
goto fail;
}
/* parse chunks (always BE) */
{
off_t chunk_offset = 0x20;
off_t file_size = get_streamfile_size(sf);
while (chunk_offset < file_size) {
uint32_t chunk_type = read_32bitBE(chunk_offset+0x00,sf);
size_t chunk_size = read_32bitBE(chunk_offset+0x08,sf); /* maybe 64b from 0x04? */
switch(chunk_type) {
case 0x464D5441: /* "FMTA" */
fmta_offset = chunk_offset + 0x18;
break;
case 0x44415441: /* "DATA" */
data_offset = chunk_offset + 0x18;
data_size = chunk_size;
break;
default: /* known: "LABL" (usually before "FMTA"), "META" (usually after "DATA") */
break;
}
chunk_offset += 0x18 + chunk_size;
}
if (!fmta_offset || !data_offset || !data_size)
goto fail;
}
/* parse FMTA / DATA (fully interleaved standard DSPs) */
channels = read_8bit(fmta_offset+0x00, sf);
/* FMTA 0x08: channel mapping */
header_offset = data_offset;
if (version == 0x0a) {
size_t align = 0x03; /* possibly 32b align */
header_offset += align;
data_size -= align;
}
start_offset = header_offset + 0x60;
loop_flag = read_16bit(header_offset + 0x0C, sf);
interleave = data_size / channels;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_RFRM;
vgmstream->sample_rate = read_32bit(header_offset + 0x08, sf);
vgmstream->num_samples = read_32bit(header_offset + 0x00, sf);
vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bit(header_offset + 0x10, sf));
vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bit(header_offset + 0x14, sf)) + 1;
if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
dsp_read_coefs(vgmstream, sf, header_offset + 0x1C, interleave, big_endian);
dsp_read_hist (vgmstream, sf, header_offset + 0x40, interleave, big_endian);
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -18,7 +18,7 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
@ -52,7 +52,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>$(VCmdAdditionalIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;$(VWmpPreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;VGM_WINAMP_UNICODE;$(VWmpPreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>