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_ */