diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bdaedba
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/vgmparse/__pycache__
diff --git a/.project b/.project
new file mode 100644
index 0000000..9299c89
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ vgmparse
+
+
+
+
+
+ org.python.pydev.PyDevBuilder
+
+
+
+
+
+ org.python.pydev.pythonNature
+
+
diff --git a/.pydevproject b/.pydevproject
new file mode 100644
index 0000000..0e3729e
--- /dev/null
+++ b/.pydevproject
@@ -0,0 +1,8 @@
+
+
+Default
+python 2.7
+
+/${PROJECT_DIR_NAME}
+
+
diff --git a/README.md b/README.md
index af7f861..397f9a3 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
A Python module for parsing [VGM (Video Game Music)](https://en.wikipedia.org/wiki/VGM_(file_format))
files. `.vgm` and `.vgz` (Gzip compressed) files are supported.
-Currently, only version 1.50 of the VGM specification is supported.
+Currently, only versions 1.01 and 1.50 of the VGM specification are supported.
## Installation
The `vgmparse` module can be installed directly from GitHub using `pip`:
@@ -79,3 +79,12 @@ then seek and read like a file:
@>>> vgm_data.data_block.read(5)
b'\x82\x88\x8a\x8a\x88'
```
+
+### Saving a VGM file
+
+You can save the VGM back into a file by using the `.save()` method:
+
+```
+@>>> vgm_out = open('newfile.vgm', 'wb')
+@>>> vgm_data.save(vgm_out)
+```
diff --git a/test/Alex Kidd in Miracle World - 01 - Title Screen.vgm b/test/Alex Kidd in Miracle World - 01 - Title Screen.vgm
new file mode 100644
index 0000000..f2ff322
Binary files /dev/null and b/test/Alex Kidd in Miracle World - 01 - Title Screen.vgm differ
diff --git a/test/test.py b/test/test.py
new file mode 100644
index 0000000..88a5bc2
--- /dev/null
+++ b/test/test.py
@@ -0,0 +1,29 @@
+import unittest
+import vgmparse
+import tempfile, time
+
+class TestParsing(unittest.TestCase):
+
+ def test_vgm_1_01(self):
+ with open('Alex Kidd in Miracle World - 01 - Title Screen.vgm', 'rb') as f:
+ file_data = f.read()
+ parser = vgmparse.Parser(file_data)
+
+ # The first command is a GG Stereo command
+ self.assertEqual(0x4F, ord(parser.command_list[0]['command']))
+ self.assertEqual(0xFF, ord(parser.command_list[0]['data']))
+
+ # The second command is a SN76496 Latch/Data command
+ self.assertEqual(0x50, ord(parser.command_list[1]['command']))
+ self.assertEqual(0x80, ord(parser.command_list[1]['data']))
+
+ def test_save(self):
+ with open('Alex Kidd in Miracle World - 01 - Title Screen.vgm', 'rb') as f:
+ file_data = f.read()
+ parser = vgmparse.Parser(file_data)
+
+ with open('{0}/test-save-{1}.vgm'.format(tempfile.gettempdir(), time.time()), 'wb') as o:
+ parser.save(o)
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/vgmparse/__init__.py b/vgmparse/__init__.py
index 7f5af13..69d1b45 100644
--- a/vgmparse/__init__.py
+++ b/vgmparse/__init__.py
@@ -18,41 +18,39 @@ class Parser:
# Supported VGM versions
supported_ver_list = [
+ 0x00000101,
0x00000150,
]
# VGM metadata offsets
metadata_offsets = {
- # Version 1.50
- 0x00000150: {
- 'vgm_ident': {'offset': 0x00, 'size': 4, 'type_format': None},
- 'eof_offset': {'offset': 0x04, 'size': 4, 'type_format': '> 8, version & 0xFF)
+
+ def save(self, buffer):
+ # Pre-fill the header with zeroes
+ buffer.seek(0)
+ buffer.write(b'\0' * 0x40)
+
+ # Iterate over the offsets and write the metadata
+ for value, offset_data in self.metadata_offsets.items():
+
+ # Seek to the data location and read the data
+ buffer.seek(offset_data['offset'])
+
+ # Unpack the data if required
+ if offset_data['type_format'] is not None:
+ data = struct.pack(
+ offset_data['type_format'],
+ self.metadata[value],
+ )
+ buffer.write(data)
+ else:
+ buffer.write(self.metadata[value])
+
+ # Write out the commands
+ for cmd in self.command_list:
+ buffer.write(cmd['command'])
+ if cmd['data']:
+ buffer.write(cmd['data'])
+
\ No newline at end of file