diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index 7a9a641b..0865b6f2 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -252,6 +252,10 @@ RelativePath=".\meta\bar_streamfile.h" > + + diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 5837fbeb..b1e77d2a 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -106,6 +106,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 30d72553..7341ba2c 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -86,6 +86,9 @@ meta\Header Files + + meta\Header Files + meta\Header Files diff --git a/src/meta/bgw.c b/src/meta/bgw.c index cb5e2d58..a73cdbd4 100644 --- a/src/meta/bgw.c +++ b/src/meta/bgw.c @@ -1,8 +1,6 @@ #include "meta.h" #include "../coding/coding.h" - - -static STREAMFILE* setup_bgw_atrac3_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, size_t frame_size, int channels); +#include "bgw_streamfile.h" /* BGW - from Final Fantasy XI (PC) music files */ @@ -220,61 +218,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - - -#define BGW_KEY_MAX (0xC0*2) - -typedef struct { - uint8_t key[BGW_KEY_MAX]; - size_t key_size; -} bgw_decryption_data; - -/* Encrypted ATRAC3 info from Moogle Toolbox (https://sourceforge.net/projects/mogbox/) */ -static size_t bgw_decryption_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, bgw_decryption_data* data) { - size_t bytes_read; - int i; - - bytes_read = streamfile->read(streamfile, dest, offset, length); - - /* decrypt data (xor) */ - for (i = 0; i < bytes_read; i++) { - dest[i] ^= data->key[(offset + i) % data->key_size]; - } - - return bytes_read; -} - -static STREAMFILE* setup_bgw_atrac3_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, size_t frame_size, int channels) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - bgw_decryption_data io_data = {0}; - size_t io_data_size = sizeof(bgw_decryption_data); - int ch; - - /* setup decryption with key (first frame + modified channel header) */ - if (frame_size*channels == 0 || frame_size*channels > BGW_KEY_MAX) goto fail; - - io_data.key_size = read_streamfile(io_data.key, subfile_offset, frame_size*channels, streamFile); - for (ch = 0; ch < channels; ch++) { - uint32_t xor = get_32bitBE(io_data.key + frame_size*ch); - put_32bitBE(io_data.key + frame_size*ch, xor ^ 0xA0024E9F); - } - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, bgw_decryption_read,NULL); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/src/meta/bgw_streamfile.h b/src/meta/bgw_streamfile.h new file mode 100644 index 00000000..f734fdce --- /dev/null +++ b/src/meta/bgw_streamfile.h @@ -0,0 +1,66 @@ +#ifndef _BGW_STREAMFILE_H_ +#define _BGW_STREAMFILE_H_ +#include "../streamfile.h" + + +#define BGW_KEY_MAX (0xC0*2) + +typedef struct { + uint8_t key[BGW_KEY_MAX]; + size_t key_size; +} bgw_decryption_data; + +/* Encrypted ATRAC3 info from Moogle Toolbox (https://sourceforge.net/projects/mogbox/) */ +static size_t bgw_decryption_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, bgw_decryption_data* data) { + size_t bytes_read; + int i; + + bytes_read = streamfile->read(streamfile, dest, offset, length); + + /* decrypt data (xor) */ + for (i = 0; i < bytes_read; i++) { + dest[i] ^= data->key[(offset + i) % data->key_size]; + } + + //todo: a few files (music069.bgw, music071.bgw, music900.bgw) have the last frames unencrypted, + // though they are blank and encoder ignores wrongly decrypted frames and outputs blank samples as well + + return bytes_read; +} + +static STREAMFILE* setup_bgw_atrac3_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, size_t frame_size, int channels) { + STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; + bgw_decryption_data io_data = {0}; + size_t io_data_size = sizeof(bgw_decryption_data); + int ch; + + /* setup decryption with key (first frame + modified channel header) */ + if (frame_size*channels == 0 || frame_size*channels > BGW_KEY_MAX) goto fail; + + io_data.key_size = read_streamfile(io_data.key, subfile_offset, frame_size*channels, streamFile); + for (ch = 0; ch < channels; ch++) { + uint32_t xor = get_32bitBE(io_data.key + frame_size*ch); + put_32bitBE(io_data.key + frame_size*ch, xor ^ 0xA0024E9F); + } + + /* setup subfile */ + new_streamFile = open_wrap_streamfile(streamFile); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, bgw_decryption_read,NULL); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + return temp_streamFile; + +fail: + close_streamfile(temp_streamFile); + return NULL; +} + +#endif /* _BGW_STREAMFILE_H_ */