diff --git a/Info.plist b/Info.plist
index a00d7d4f0..5092a6acf 100644
--- a/Info.plist
+++ b/Info.plist
@@ -22,6 +22,20 @@
CFBundleTypeRole
None
+
+ CFBundleTypeExtensions
+
+ mo3
+
+ LSTypeIsPackage
+
+ CFBundleTypeRole
+ Viewer
+ CFBundleTypeIconFile
+ song.icns
+ CFBundleTypeName
+ MO3 Audio File
+
CFBundleTypeExtensions
diff --git a/Plugins/Dumb/Dumb.xcodeproj/project.pbxproj b/Plugins/Dumb/Dumb.xcodeproj/project.pbxproj
index a7d281006..ccd30fa76 100644
--- a/Plugins/Dumb/Dumb.xcodeproj/project.pbxproj
+++ b/Plugins/Dumb/Dumb.xcodeproj/project.pbxproj
@@ -19,6 +19,9 @@
8337AAEE17FFA0000081AFF8 /* unrealfmtdata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8337AAEA17FFA0000081AFF8 /* unrealfmtdata.cpp */; };
8337AAF117FFA2D30081AFF8 /* j2b.c in Sources */ = {isa = PBXBuildFile; fileRef = 8337AAEF17FFA2D30081AFF8 /* j2b.c */; };
8337AAF317FFA7640081AFF8 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8337AAF217FFA7640081AFF8 /* libz.dylib */; };
+ 83527EE818242FD5002F170E /* libunmo3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83527EE618242FD5002F170E /* libunmo3.dylib */; };
+ 83527EEB18243069002F170E /* mo3.c in Sources */ = {isa = PBXBuildFile; fileRef = 83527EEA18243069002F170E /* mo3.c */; };
+ 83527EED182432CA002F170E /* libunmo3.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83527EE618242FD5002F170E /* libunmo3.dylib */; };
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
/* End PBXBuildFile section */
@@ -53,6 +56,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 83527EEC182432BD002F170E /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 6;
+ files = (
+ 83527EED182432CA002F170E /* libunmo3.dylib in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@@ -78,6 +91,10 @@
8337AAEF17FFA2D30081AFF8 /* j2b.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = j2b.c; sourceTree = ""; };
8337AAF017FFA2D30081AFF8 /* j2b.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = j2b.h; sourceTree = ""; };
8337AAF217FFA7640081AFF8 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
+ 83527EE618242FD5002F170E /* libunmo3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libunmo3.dylib; path = ../../../ThirdParty/BASS/libunmo3.dylib; sourceTree = ""; };
+ 83527EE718242FD5002F170E /* unmo3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unmo3.h; path = ../../../ThirdParty/BASS/unmo3.h; sourceTree = ""; };
+ 83527EE918243029002F170E /* mo3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mo3.h; path = mo3/mo3.h; sourceTree = ""; };
+ 83527EEA18243069002F170E /* mo3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mo3.c; path = mo3/mo3.c; sourceTree = ""; };
8384912B1808155E00E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = ""; };
8D5B49B6048680CD000E48DA /* Dumb.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Dumb.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
@@ -90,6 +107,7 @@
buildActionMask = 2147483647;
files = (
8337AAF317FFA7640081AFF8 /* libz.dylib in Frameworks */,
+ 83527EE818242FD5002F170E /* libunmo3.dylib in Frameworks */,
17C8F7B90CBEF380008D969D /* Dumb.framework in Frameworks */,
8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */,
);
@@ -191,6 +209,7 @@
8337AAE317FFA0000081AFF8 /* archive */ = {
isa = PBXGroup;
children = (
+ 83527EE518242FBE002F170E /* mo3 */,
8337AAE417FFA0000081AFF8 /* j2b */,
8337AAE517FFA0000081AFF8 /* umx */,
);
@@ -219,6 +238,17 @@
path = umx;
sourceTree = "";
};
+ 83527EE518242FBE002F170E /* mo3 */ = {
+ isa = PBXGroup;
+ children = (
+ 83527EEA18243069002F170E /* mo3.c */,
+ 83527EE918243029002F170E /* mo3.h */,
+ 83527EE618242FD5002F170E /* libunmo3.dylib */,
+ 83527EE718242FD5002F170E /* unmo3.h */,
+ );
+ name = mo3;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -230,6 +260,7 @@
8D5B49B1048680CD000E48DA /* Sources */,
8D5B49B3048680CD000E48DA /* Frameworks */,
17C8F6A20CBEE86E008D969D /* CopyFiles */,
+ 83527EEC182432BD002F170E /* CopyFiles */,
);
buildRules = (
);
@@ -303,6 +334,7 @@
8337AAEC17FFA0000081AFF8 /* umx.mm in Sources */,
8335FF6717FF6FD9002D8DD2 /* DumbContainer.m in Sources */,
17C8F6950CBEE846008D969D /* DumbDecoder.m in Sources */,
+ 83527EEB18243069002F170E /* mo3.c in Sources */,
8337AAEE17FFA0000081AFF8 /* unrealfmtdata.cpp in Sources */,
17DA363E0CC0600E0003F6B2 /* DumbMetadataReader.m in Sources */,
);
@@ -347,6 +379,10 @@
);
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ /Users/Chris/Source/Repos/cog/ThirdParty/BASS,
+ );
OBJROOT = ../../build;
PRODUCT_NAME = Dumb;
SKIP_INSTALL = YES;
@@ -369,6 +405,10 @@
);
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ /Users/Chris/Source/Repos/cog/ThirdParty/BASS,
+ );
OBJROOT = ../../build;
PRODUCT_NAME = Dumb;
SKIP_INSTALL = YES;
diff --git a/Plugins/Dumb/DumbDecoder.m b/Plugins/Dumb/DumbDecoder.m
index af52f3c6a..f4d18a894 100755
--- a/Plugins/Dumb/DumbDecoder.m
+++ b/Plugins/Dumb/DumbDecoder.m
@@ -10,6 +10,7 @@
#import "umx.h"
#import "j2b.h"
+#import "mo3.h"
#import "Logging.h"
@@ -19,6 +20,7 @@ struct MEMANDFREEFILE
{
char *ptr, *ptr_begin;
long left, size;
+ int is_mo3;
};
static int dumb_maffile_skip(void *f, long n)
@@ -51,7 +53,8 @@ static long dumb_maffile_getnc(char *ptr, long n, void *f)
static void dumb_maffile_close(void *f)
{
struct MEMANDFREEFILE *m = f;
- free(m->ptr_begin);
+ if (m->is_mo3) freeMo3(m->ptr_begin);
+ else free(m->ptr_begin);
free(f);
}
@@ -83,17 +86,26 @@ static const DUMBFILE_SYSTEM maffile_dfs = {
DUMBFILE *dumbfile_open_memory_and_free(char *data, long size)
{
- char * try_data = unpackUmx( data, &size );
+ int is_mo3 = 0;
+ char * try_data = unpackMo3( data, &size );
if ( try_data ) {
free( data );
data = try_data;
+ is_mo3 = 1;
}
else {
- try_data = unpackJ2b( data, &size );
+ try_data = unpackUmx( data, &size );
if ( try_data ) {
free( data );
data = try_data;
}
+ else {
+ try_data = unpackJ2b( data, &size );
+ if ( try_data ) {
+ free( data );
+ data = try_data;
+ }
+ }
}
struct MEMANDFREEFILE *m = malloc(sizeof(*m));
@@ -103,6 +115,7 @@ DUMBFILE *dumbfile_open_memory_and_free(char *data, long size)
m->ptr = data;
m->left = size;
m->size = size;
+ m->is_mo3 = is_mo3;
return dumbfile_open_ex(m, &maffile_dfs);
}
@@ -319,7 +332,7 @@ int callbackLoop(void *data)
+ (NSArray *)fileTypes
{
- return [NSArray arrayWithObjects:@"it", @"itz", @"xm", @"xmz", @"s3m", @"s3z", @"mod", @"mdz", @"stm", @"stz", @"ptm", @"mtm", @"669", @"psm", @"am", @"j2b", @"dsm", @"amf", @"okt", @"okta", @"umx", nil];
+ return [NSArray arrayWithObjects:@"it", @"itz", @"xm", @"xmz", @"s3m", @"s3z", @"mod", @"mdz", @"stm", @"stz", @"ptm", @"mtm", @"669", @"psm", @"am", @"j2b", @"dsm", @"amf", @"okt", @"okta", @"umx", @"mo3", nil];
}
+ (NSArray *)mimeTypes
diff --git a/Plugins/Dumb/archive/j2b/j2b.h b/Plugins/Dumb/archive/j2b/j2b.h
index 6042b2a46..95c9b745b 100644
--- a/Plugins/Dumb/archive/j2b/j2b.h
+++ b/Plugins/Dumb/archive/j2b/j2b.h
@@ -1,5 +1,5 @@
//
-// umx.h
+// j2b.h
// Dumb J2B Archive parser
//
// Created by Christopher Snowhill on 10/4/13.
diff --git a/Plugins/Dumb/archive/mo3/mo3.c b/Plugins/Dumb/archive/mo3/mo3.c
new file mode 100644
index 000000000..eacbdc2d0
--- /dev/null
+++ b/Plugins/Dumb/archive/mo3/mo3.c
@@ -0,0 +1,44 @@
+//
+// mo3.c
+// Dumb MO3 Archive parser
+//
+// Created by Christopher Snowhill on 11/1/13.
+// Copyright 2013 __NoWork, Inc__. All rights reserved.
+//
+
+#include "mo3.h"
+
+#include
+typedef uint32_t DWORD;
+
+#include "unmo3.h"
+
+#include
+#include
+
+void * unpackMo3( const void * in, long * size )
+{
+ void * data;
+ int len;
+
+ if ( *size > INT_MAX )
+ return 0;
+
+ if ( memcmp( in, "MO3", 3 ) != 0 )
+ return 0;
+
+ data = (void *) in;
+ len = (int) *size;
+
+ if ( UNMO3_Decode( &data, &len, 0 ) != 0 )
+ return 0;
+
+ *size = len;
+
+ return data;
+}
+
+void freeMo3( void * in )
+{
+ UNMO3_Free( in );
+}
diff --git a/Plugins/Dumb/archive/mo3/mo3.h b/Plugins/Dumb/archive/mo3/mo3.h
new file mode 100644
index 000000000..ad73dea22
--- /dev/null
+++ b/Plugins/Dumb/archive/mo3/mo3.h
@@ -0,0 +1,16 @@
+//
+// mo3.h
+// Dumb MO3 Archive parser
+//
+// Created by Christopher Snowhill on 11/1/13.
+// Copyright 2013 __NoWork, Inc__. All rights reserved.
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ extern void * unpackMo3( const void * in, long * size );
+ extern void freeMo3( void * in );
+#ifdef __cplusplus
+};
+#endif
diff --git a/ThirdParty/BASS/libunmo3.dylib b/ThirdParty/BASS/libunmo3.dylib
new file mode 100755
index 000000000..67e9ced3b
Binary files /dev/null and b/ThirdParty/BASS/libunmo3.dylib differ
diff --git a/ThirdParty/BASS/unmo3.h b/ThirdParty/BASS/unmo3.h
new file mode 100755
index 000000000..88a2c114f
--- /dev/null
+++ b/ThirdParty/BASS/unmo3.h
@@ -0,0 +1,33 @@
+/*
+ UNMO3 library C/C++ header file
+ Copyright (c) 2010-2013 Un4seen Developments Ltd.
+
+ Free for non-commercial use
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _WIN32
+#define WINAPI
+#endif
+
+// Get the UNMO3 library version
+DWORD WINAPI UNMO3_GetVersion();
+
+// Decode a MO3 file
+// in: data/len = MO3 data/len
+// out: data/len = decoded data/len (if successful)
+// return: 0 = Success, 2 = It isn't a MO3 file, 3 = There was a problem decoding the MO3 file
+int WINAPI UNMO3_Decode(void **data, int *len, DWORD flags);
+
+// UNMO3_Decode flags
+#define UNMO3_DECODE_NOSAMPLES 1 // don't process sample data
+
+// Free the data returned by UNMO3_Decode
+void WINAPI UNMO3_Free(void *data);
+
+#ifdef __cplusplus
+}
+#endif