diff --git a/Frameworks/HighlyAdvanced/HighlyAdvanced.xcodeproj/project.pbxproj b/Frameworks/HighlyAdvanced/HighlyAdvanced.xcodeproj/project.pbxproj
index ea3adbca1..ada591d26 100644
--- a/Frameworks/HighlyAdvanced/HighlyAdvanced.xcodeproj/project.pbxproj
+++ b/Frameworks/HighlyAdvanced/HighlyAdvanced.xcodeproj/project.pbxproj
@@ -328,7 +328,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.6;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
@@ -360,7 +360,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.6;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = macosx;
};
name = Release;
diff --git a/Frameworks/HighlyAdvanced/HighlyAdvanced/HighlyAdvanced-Info.plist b/Frameworks/HighlyAdvanced/HighlyAdvanced/HighlyAdvanced-Info.plist
index 02c2a8310..187cd6eea 100644
--- a/Frameworks/HighlyAdvanced/HighlyAdvanced/HighlyAdvanced-Info.plist
+++ b/Frameworks/HighlyAdvanced/HighlyAdvanced/HighlyAdvanced-Info.plist
@@ -9,7 +9,7 @@
CFBundleIconFile
CFBundleIdentifier
- NoWork-Inc.${PRODUCT_NAME:rfc1034identifier}
+ org.nowork.highlyadvanced
CFBundleInfoDictionaryVersion
6.0
CFBundleName
diff --git a/Frameworks/HighlyExperimental/HighlyExperimental.xcodeproj/project.pbxproj b/Frameworks/HighlyExperimental/HighlyExperimental.xcodeproj/project.pbxproj
index 2cc2ee6fe..5ebdbaea4 100644
--- a/Frameworks/HighlyExperimental/HighlyExperimental.xcodeproj/project.pbxproj
+++ b/Frameworks/HighlyExperimental/HighlyExperimental.xcodeproj/project.pbxproj
@@ -265,7 +265,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.6;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
@@ -297,7 +297,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.6;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = macosx;
};
name = Release;
@@ -320,7 +320,6 @@
);
INFOPLIST_FILE = "HighlyExperimental/HighlyExperimental-Info.plist";
INSTALL_PATH = "@loader_path/../Frameworks";
- MACOSX_DEPLOYMENT_TARGET = 10.6;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
WRAPPER_EXTENSION = framework;
@@ -344,7 +343,6 @@
);
INFOPLIST_FILE = "HighlyExperimental/HighlyExperimental-Info.plist";
INSTALL_PATH = "@loader_path/../Frameworks";
- MACOSX_DEPLOYMENT_TARGET = 10.6;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
WRAPPER_EXTENSION = framework;
diff --git a/Frameworks/HighlyExperimental/HighlyExperimental/HighlyExperimental-Info.plist b/Frameworks/HighlyExperimental/HighlyExperimental/HighlyExperimental-Info.plist
index 02c2a8310..54b5dd836 100644
--- a/Frameworks/HighlyExperimental/HighlyExperimental/HighlyExperimental-Info.plist
+++ b/Frameworks/HighlyExperimental/HighlyExperimental/HighlyExperimental-Info.plist
@@ -9,7 +9,7 @@
CFBundleIconFile
CFBundleIdentifier
- NoWork-Inc.${PRODUCT_NAME:rfc1034identifier}
+ org.nowork.highlyexperimental
CFBundleInfoDictionaryVersion
6.0
CFBundleName
diff --git a/Frameworks/HighlyQuixotic/HighlyQuixotic.xcodeproj/project.pbxproj b/Frameworks/HighlyQuixotic/HighlyQuixotic.xcodeproj/project.pbxproj
index a7c643d18..bfab909a5 100644
--- a/Frameworks/HighlyQuixotic/HighlyQuixotic.xcodeproj/project.pbxproj
+++ b/Frameworks/HighlyQuixotic/HighlyQuixotic.xcodeproj/project.pbxproj
@@ -235,7 +235,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.6;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SKIP_INSTALL = YES;
@@ -273,7 +273,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.6;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = macosx;
SKIP_INSTALL = YES;
};
diff --git a/Frameworks/HighlyQuixotic/HighlyQuixotic/HighlyQuixotic-Info.plist b/Frameworks/HighlyQuixotic/HighlyQuixotic/HighlyQuixotic-Info.plist
index 02c2a8310..8107516ff 100644
--- a/Frameworks/HighlyQuixotic/HighlyQuixotic/HighlyQuixotic-Info.plist
+++ b/Frameworks/HighlyQuixotic/HighlyQuixotic/HighlyQuixotic-Info.plist
@@ -9,7 +9,7 @@
CFBundleIconFile
CFBundleIdentifier
- NoWork-Inc.${PRODUCT_NAME:rfc1034identifier}
+ org.nowork.highlyquixotic
CFBundleInfoDictionaryVersion
6.0
CFBundleName
diff --git a/Frameworks/HighlyTheoretical/HighlyTheoretical.xcodeproj/project.pbxproj b/Frameworks/HighlyTheoretical/HighlyTheoretical.xcodeproj/project.pbxproj
index d8ffc44ec..ba419085b 100644
--- a/Frameworks/HighlyTheoretical/HighlyTheoretical.xcodeproj/project.pbxproj
+++ b/Frameworks/HighlyTheoretical/HighlyTheoretical.xcodeproj/project.pbxproj
@@ -283,7 +283,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.6;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
@@ -323,7 +323,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.6;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = macosx;
};
name = Release;
diff --git a/Frameworks/HighlyTheoretical/HighlyTheoretical/HighlyTheoretical-Info.plist b/Frameworks/HighlyTheoretical/HighlyTheoretical/HighlyTheoretical-Info.plist
index 02c2a8310..42541574a 100644
--- a/Frameworks/HighlyTheoretical/HighlyTheoretical/HighlyTheoretical-Info.plist
+++ b/Frameworks/HighlyTheoretical/HighlyTheoretical/HighlyTheoretical-Info.plist
@@ -9,7 +9,7 @@
CFBundleIconFile
CFBundleIdentifier
- NoWork-Inc.${PRODUCT_NAME:rfc1034identifier}
+ org.nowork.highlytheoretical
CFBundleInfoDictionaryVersion
6.0
CFBundleName
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer.xcodeproj/project.pbxproj b/Frameworks/SSEQPlayer/SSEQPlayer.xcodeproj/project.pbxproj
new file mode 100644
index 000000000..d6aa929c1
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer.xcodeproj/project.pbxproj
@@ -0,0 +1,446 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 83848FBC1807623F00E7332D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83848FBB1807623F00E7332D /* Cocoa.framework */; };
+ 83848FC61807623F00E7332D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83848FC41807623F00E7332D /* InfoPlist.strings */; };
+ 838490241807649A00E7332D /* BigSString.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490001807649A00E7332D /* BigSString.h */; };
+ 838490251807649A00E7332D /* Channel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 838490011807649A00E7332D /* Channel.cpp */; };
+ 838490261807649A00E7332D /* Channel.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490021807649A00E7332D /* Channel.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 838490271807649A00E7332D /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490031807649A00E7332D /* common.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 838490281807649A00E7332D /* consts.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490041807649A00E7332D /* consts.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 838490291807649A00E7332D /* convert.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490051807649A00E7332D /* convert.h */; };
+ 8384902A1807649A00E7332D /* ConvertUTF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 838490061807649A00E7332D /* ConvertUTF.cpp */; };
+ 8384902B1807649A00E7332D /* ConvertUTF.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490071807649A00E7332D /* ConvertUTF.h */; };
+ 8384902C1807649A00E7332D /* FATSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 838490081807649A00E7332D /* FATSection.cpp */; };
+ 8384902D1807649A00E7332D /* FATSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490091807649A00E7332D /* FATSection.h */; };
+ 8384902E1807649A00E7332D /* INFOEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8384900A1807649A00E7332D /* INFOEntry.cpp */; };
+ 8384902F1807649A00E7332D /* INFOEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 8384900B1807649A00E7332D /* INFOEntry.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 838490301807649A00E7332D /* INFOSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8384900C1807649A00E7332D /* INFOSection.cpp */; };
+ 838490311807649A00E7332D /* INFOSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 8384900D1807649A00E7332D /* INFOSection.h */; };
+ 838490321807649A00E7332D /* NDSStdHeader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8384900E1807649A00E7332D /* NDSStdHeader.cpp */; };
+ 838490331807649A00E7332D /* NDSStdHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8384900F1807649A00E7332D /* NDSStdHeader.h */; };
+ 838490341807649A00E7332D /* Player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 838490101807649A00E7332D /* Player.cpp */; };
+ 838490351807649A00E7332D /* Player.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490111807649A00E7332D /* Player.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 838490361807649A00E7332D /* SBNK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 838490121807649A00E7332D /* SBNK.cpp */; };
+ 838490371807649A00E7332D /* SBNK.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490131807649A00E7332D /* SBNK.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 838490381807649A00E7332D /* SDAT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 838490141807649A00E7332D /* SDAT.cpp */; };
+ 838490391807649A00E7332D /* SDAT.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490151807649A00E7332D /* SDAT.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8384903A1807649A00E7332D /* SSEQ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 838490161807649A00E7332D /* SSEQ.cpp */; };
+ 8384903B1807649A00E7332D /* SSEQ.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490171807649A00E7332D /* SSEQ.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8384903C1807649A00E7332D /* SWAR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 838490181807649A00E7332D /* SWAR.cpp */; };
+ 8384903D1807649A00E7332D /* SWAR.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490191807649A00E7332D /* SWAR.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8384903E1807649A00E7332D /* SWAV.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8384901A1807649A00E7332D /* SWAV.cpp */; };
+ 8384903F1807649A00E7332D /* SWAV.h in Headers */ = {isa = PBXBuildFile; fileRef = 8384901B1807649A00E7332D /* SWAV.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 838490401807649A00E7332D /* SYMBSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8384901C1807649A00E7332D /* SYMBSection.cpp */; };
+ 838490411807649A00E7332D /* SYMBSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 8384901D1807649A00E7332D /* SYMBSection.h */; };
+ 838490421807649A00E7332D /* Track.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8384901E1807649A00E7332D /* Track.cpp */; };
+ 838490431807649A00E7332D /* Track.h in Headers */ = {isa = PBXBuildFile; fileRef = 8384901F1807649A00E7332D /* Track.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 838490441807649A00E7332D /* UtfConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 838490201807649A00E7332D /* UtfConverter.cpp */; };
+ 838490451807649A00E7332D /* UtfConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490211807649A00E7332D /* UtfConverter.h */; };
+ 838490461807649A00E7332D /* UTFEncodeDecode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 838490221807649A00E7332D /* UTFEncodeDecode.cpp */; };
+ 838490471807649A00E7332D /* UTFEncodeDecode.h in Headers */ = {isa = PBXBuildFile; fileRef = 838490231807649A00E7332D /* UTFEncodeDecode.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 83848FB81807623F00E7332D /* SSEQPlayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SSEQPlayer.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 83848FBB1807623F00E7332D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+ 83848FBE1807623F00E7332D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 83848FBF1807623F00E7332D /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
+ 83848FC01807623F00E7332D /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
+ 83848FC31807623F00E7332D /* SSEQPlayer-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SSEQPlayer-Info.plist"; sourceTree = ""; };
+ 83848FC51807623F00E7332D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
+ 83848FD01807623F00E7332D /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
+ 838490001807649A00E7332D /* BigSString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BigSString.h; sourceTree = ""; };
+ 838490011807649A00E7332D /* Channel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Channel.cpp; sourceTree = ""; };
+ 838490021807649A00E7332D /* Channel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Channel.h; sourceTree = ""; };
+ 838490031807649A00E7332D /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; };
+ 838490041807649A00E7332D /* consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = consts.h; sourceTree = ""; };
+ 838490051807649A00E7332D /* convert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = convert.h; sourceTree = ""; };
+ 838490061807649A00E7332D /* ConvertUTF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConvertUTF.cpp; sourceTree = ""; };
+ 838490071807649A00E7332D /* ConvertUTF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConvertUTF.h; sourceTree = ""; };
+ 838490081807649A00E7332D /* FATSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FATSection.cpp; sourceTree = ""; };
+ 838490091807649A00E7332D /* FATSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FATSection.h; sourceTree = ""; };
+ 8384900A1807649A00E7332D /* INFOEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = INFOEntry.cpp; sourceTree = ""; };
+ 8384900B1807649A00E7332D /* INFOEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INFOEntry.h; sourceTree = ""; };
+ 8384900C1807649A00E7332D /* INFOSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = INFOSection.cpp; sourceTree = ""; };
+ 8384900D1807649A00E7332D /* INFOSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INFOSection.h; sourceTree = ""; };
+ 8384900E1807649A00E7332D /* NDSStdHeader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NDSStdHeader.cpp; sourceTree = ""; };
+ 8384900F1807649A00E7332D /* NDSStdHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NDSStdHeader.h; sourceTree = ""; };
+ 838490101807649A00E7332D /* Player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Player.cpp; sourceTree = ""; };
+ 838490111807649A00E7332D /* Player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Player.h; sourceTree = ""; };
+ 838490121807649A00E7332D /* SBNK.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SBNK.cpp; sourceTree = ""; };
+ 838490131807649A00E7332D /* SBNK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBNK.h; sourceTree = ""; };
+ 838490141807649A00E7332D /* SDAT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SDAT.cpp; sourceTree = ""; };
+ 838490151807649A00E7332D /* SDAT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDAT.h; sourceTree = ""; };
+ 838490161807649A00E7332D /* SSEQ.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SSEQ.cpp; sourceTree = ""; };
+ 838490171807649A00E7332D /* SSEQ.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSEQ.h; sourceTree = ""; };
+ 838490181807649A00E7332D /* SWAR.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWAR.cpp; sourceTree = ""; };
+ 838490191807649A00E7332D /* SWAR.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWAR.h; sourceTree = ""; };
+ 8384901A1807649A00E7332D /* SWAV.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWAV.cpp; sourceTree = ""; };
+ 8384901B1807649A00E7332D /* SWAV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWAV.h; sourceTree = ""; };
+ 8384901C1807649A00E7332D /* SYMBSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SYMBSection.cpp; sourceTree = ""; };
+ 8384901D1807649A00E7332D /* SYMBSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SYMBSection.h; sourceTree = ""; };
+ 8384901E1807649A00E7332D /* Track.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Track.cpp; sourceTree = ""; };
+ 8384901F1807649A00E7332D /* Track.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Track.h; sourceTree = ""; };
+ 838490201807649A00E7332D /* UtfConverter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UtfConverter.cpp; sourceTree = ""; };
+ 838490211807649A00E7332D /* UtfConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UtfConverter.h; sourceTree = ""; };
+ 838490221807649A00E7332D /* UTFEncodeDecode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UTFEncodeDecode.cpp; sourceTree = ""; };
+ 838490231807649A00E7332D /* UTFEncodeDecode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UTFEncodeDecode.h; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 83848FB41807623F00E7332D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 83848FBC1807623F00E7332D /* Cocoa.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 83848FAE1807623F00E7332D = {
+ isa = PBXGroup;
+ children = (
+ 83848FC11807623F00E7332D /* SSEQPlayer */,
+ 83848FBA1807623F00E7332D /* Frameworks */,
+ 83848FB91807623F00E7332D /* Products */,
+ );
+ sourceTree = "";
+ };
+ 83848FB91807623F00E7332D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 83848FB81807623F00E7332D /* SSEQPlayer.framework */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 83848FBA1807623F00E7332D /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 83848FBB1807623F00E7332D /* Cocoa.framework */,
+ 83848FD01807623F00E7332D /* XCTest.framework */,
+ 83848FBD1807623F00E7332D /* Other Frameworks */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 83848FBD1807623F00E7332D /* Other Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 83848FBE1807623F00E7332D /* Foundation.framework */,
+ 83848FBF1807623F00E7332D /* CoreData.framework */,
+ 83848FC01807623F00E7332D /* AppKit.framework */,
+ );
+ name = "Other Frameworks";
+ sourceTree = "";
+ };
+ 83848FC11807623F00E7332D /* SSEQPlayer */ = {
+ isa = PBXGroup;
+ children = (
+ 838490001807649A00E7332D /* BigSString.h */,
+ 838490011807649A00E7332D /* Channel.cpp */,
+ 838490021807649A00E7332D /* Channel.h */,
+ 838490031807649A00E7332D /* common.h */,
+ 838490041807649A00E7332D /* consts.h */,
+ 838490051807649A00E7332D /* convert.h */,
+ 838490061807649A00E7332D /* ConvertUTF.cpp */,
+ 838490071807649A00E7332D /* ConvertUTF.h */,
+ 838490081807649A00E7332D /* FATSection.cpp */,
+ 838490091807649A00E7332D /* FATSection.h */,
+ 8384900A1807649A00E7332D /* INFOEntry.cpp */,
+ 8384900B1807649A00E7332D /* INFOEntry.h */,
+ 8384900C1807649A00E7332D /* INFOSection.cpp */,
+ 8384900D1807649A00E7332D /* INFOSection.h */,
+ 8384900E1807649A00E7332D /* NDSStdHeader.cpp */,
+ 8384900F1807649A00E7332D /* NDSStdHeader.h */,
+ 838490101807649A00E7332D /* Player.cpp */,
+ 838490111807649A00E7332D /* Player.h */,
+ 838490121807649A00E7332D /* SBNK.cpp */,
+ 838490131807649A00E7332D /* SBNK.h */,
+ 838490141807649A00E7332D /* SDAT.cpp */,
+ 838490151807649A00E7332D /* SDAT.h */,
+ 838490161807649A00E7332D /* SSEQ.cpp */,
+ 838490171807649A00E7332D /* SSEQ.h */,
+ 838490181807649A00E7332D /* SWAR.cpp */,
+ 838490191807649A00E7332D /* SWAR.h */,
+ 8384901A1807649A00E7332D /* SWAV.cpp */,
+ 8384901B1807649A00E7332D /* SWAV.h */,
+ 8384901C1807649A00E7332D /* SYMBSection.cpp */,
+ 8384901D1807649A00E7332D /* SYMBSection.h */,
+ 8384901E1807649A00E7332D /* Track.cpp */,
+ 8384901F1807649A00E7332D /* Track.h */,
+ 838490201807649A00E7332D /* UtfConverter.cpp */,
+ 838490211807649A00E7332D /* UtfConverter.h */,
+ 838490221807649A00E7332D /* UTFEncodeDecode.cpp */,
+ 838490231807649A00E7332D /* UTFEncodeDecode.h */,
+ 83848FC21807623F00E7332D /* Supporting Files */,
+ );
+ path = SSEQPlayer;
+ sourceTree = "";
+ };
+ 83848FC21807623F00E7332D /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 83848FC31807623F00E7332D /* SSEQPlayer-Info.plist */,
+ 83848FC41807623F00E7332D /* InfoPlist.strings */,
+ );
+ name = "Supporting Files";
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 83848FB51807623F00E7332D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8384902F1807649A00E7332D /* INFOEntry.h in Headers */,
+ 838490281807649A00E7332D /* consts.h in Headers */,
+ 838490261807649A00E7332D /* Channel.h in Headers */,
+ 838490431807649A00E7332D /* Track.h in Headers */,
+ 8384903B1807649A00E7332D /* SSEQ.h in Headers */,
+ 838490371807649A00E7332D /* SBNK.h in Headers */,
+ 8384903D1807649A00E7332D /* SWAR.h in Headers */,
+ 8384903F1807649A00E7332D /* SWAV.h in Headers */,
+ 838490271807649A00E7332D /* common.h in Headers */,
+ 838490391807649A00E7332D /* SDAT.h in Headers */,
+ 838490351807649A00E7332D /* Player.h in Headers */,
+ 838490471807649A00E7332D /* UTFEncodeDecode.h in Headers */,
+ 838490311807649A00E7332D /* INFOSection.h in Headers */,
+ 8384902B1807649A00E7332D /* ConvertUTF.h in Headers */,
+ 838490451807649A00E7332D /* UtfConverter.h in Headers */,
+ 8384902D1807649A00E7332D /* FATSection.h in Headers */,
+ 838490331807649A00E7332D /* NDSStdHeader.h in Headers */,
+ 838490291807649A00E7332D /* convert.h in Headers */,
+ 838490411807649A00E7332D /* SYMBSection.h in Headers */,
+ 838490241807649A00E7332D /* BigSString.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 83848FB71807623F00E7332D /* SSEQPlayer */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 83848FE01807623F00E7332D /* Build configuration list for PBXNativeTarget "SSEQPlayer" */;
+ buildPhases = (
+ 83848FB31807623F00E7332D /* Sources */,
+ 83848FB41807623F00E7332D /* Frameworks */,
+ 83848FB51807623F00E7332D /* Headers */,
+ 83848FB61807623F00E7332D /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = SSEQPlayer;
+ productName = SSEQPlayer;
+ productReference = 83848FB81807623F00E7332D /* SSEQPlayer.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 83848FAF1807623F00E7332D /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0500;
+ ORGANIZATIONNAME = "Christopher Snowhill";
+ };
+ buildConfigurationList = 83848FB21807623F00E7332D /* Build configuration list for PBXProject "SSEQPlayer" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 83848FAE1807623F00E7332D;
+ productRefGroup = 83848FB91807623F00E7332D /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 83848FB71807623F00E7332D /* SSEQPlayer */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 83848FB61807623F00E7332D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 83848FC61807623F00E7332D /* InfoPlist.strings in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 83848FB31807623F00E7332D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 838490441807649A00E7332D /* UtfConverter.cpp in Sources */,
+ 838490381807649A00E7332D /* SDAT.cpp in Sources */,
+ 8384902E1807649A00E7332D /* INFOEntry.cpp in Sources */,
+ 838490341807649A00E7332D /* Player.cpp in Sources */,
+ 838490301807649A00E7332D /* INFOSection.cpp in Sources */,
+ 838490461807649A00E7332D /* UTFEncodeDecode.cpp in Sources */,
+ 838490251807649A00E7332D /* Channel.cpp in Sources */,
+ 8384903C1807649A00E7332D /* SWAR.cpp in Sources */,
+ 8384903E1807649A00E7332D /* SWAV.cpp in Sources */,
+ 838490421807649A00E7332D /* Track.cpp in Sources */,
+ 8384902C1807649A00E7332D /* FATSection.cpp in Sources */,
+ 838490321807649A00E7332D /* NDSStdHeader.cpp in Sources */,
+ 8384902A1807649A00E7332D /* ConvertUTF.cpp in Sources */,
+ 838490401807649A00E7332D /* SYMBSection.cpp in Sources */,
+ 838490361807649A00E7332D /* SBNK.cpp in Sources */,
+ 8384903A1807649A00E7332D /* SSEQ.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 83848FC41807623F00E7332D /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 83848FC51807623F00E7332D /* en */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 83848FDE1807623F00E7332D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_OBJC_ARC = NO;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ 83848FDF1807623F00E7332D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_OBJC_ARC = NO;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ 83848FE11807623F00E7332D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ INFOPLIST_FILE = "SSEQPlayer/SSEQPlayer-Info.plist";
+ INSTALL_PATH = "@loader_path/../Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Debug;
+ };
+ 83848FE21807623F00E7332D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ INFOPLIST_FILE = "SSEQPlayer/SSEQPlayer-Info.plist";
+ INSTALL_PATH = "@loader_path/../Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 83848FB21807623F00E7332D /* Build configuration list for PBXProject "SSEQPlayer" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 83848FDE1807623F00E7332D /* Debug */,
+ 83848FDF1807623F00E7332D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 83848FE01807623F00E7332D /* Build configuration list for PBXNativeTarget "SSEQPlayer" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 83848FE11807623F00E7332D /* Debug */,
+ 83848FE21807623F00E7332D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 83848FAF1807623F00E7332D /* Project object */;
+}
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/BigSString.h b/Frameworks/SSEQPlayer/SSEQPlayer/BigSString.h
new file mode 100644
index 000000000..d40ce8b58
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/BigSString.h
@@ -0,0 +1,220 @@
+/*
+ * String class in ANSI (or rather, current Windows code page), UTF-8, and UTF-16
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ * Last modification on 2013-03-25
+ */
+
+#ifndef BIGSSTRING_H
+#define BIGSSTRING_H
+
+#include
+#include
+#include
+#include "UtfConverter.h"
+#include "UTFEncodeDecode.h"
+
+class String
+{
+public:
+ String(const std::locale &L = std::locale::classic()) : ansi(""), utf8(""), utf16(L""), loc(L) { }
+ String(const char *new_str, bool is_utf8 = false, const std::locale &L = std::locale::classic()) : ansi(is_utf8 ? DecodeFromUTF8(new_str, L) : new_str), utf8(is_utf8 ? new_str : EncodeToUTF8(new_str, L)),
+ utf16(UtfConverter::FromUtf8(utf8)), loc(L) { }
+ String(const std::string &new_str, bool is_utf8 = false, const std::locale &L = std::locale::classic()) : ansi(is_utf8 ? DecodeFromUTF8(new_str, L) : new_str), utf8(is_utf8 ? new_str : EncodeToUTF8(new_str, L)),
+ utf16(UtfConverter::FromUtf8(utf8)), loc(L) { }
+ String(const wchar_t *new_wstr, const std::locale &L = std::locale::classic()) : ansi(DecodeFromUTF8(UtfConverter::ToUtf8(new_wstr), L)), utf8(UtfConverter::ToUtf8(new_wstr)), utf16(new_wstr), loc(L) { }
+ String(const std::wstring &new_wstr, const std::locale &L = std::locale::classic()) : ansi(DecodeFromUTF8(UtfConverter::ToUtf8(new_wstr), L)), utf8(UtfConverter::ToUtf8(new_wstr)), utf16(new_wstr), loc(L) { }
+ bool empty() const { return this->utf8.empty(); }
+ std::string GetAnsi() const { return this->ansi; }
+ const char *GetAnsiC() const { return this->ansi.c_str(); }
+ std::string GetStr() const { return this->utf8; }
+ const char *GetStrC() const { return this->utf8.c_str(); }
+ std::wstring GetWStr() const { return this->utf16; }
+ const wchar_t *GetWStrC() const { return this->utf16.c_str(); }
+ bool operator==(const String &str2) const
+ {
+ return this->utf8 == str2.utf8;
+ }
+ String &operator=(const std::string &new_str)
+ {
+ this->ansi = DecodeFromUTF8(new_str, this->loc);
+ this->utf8 = new_str;
+ this->utf16 = UtfConverter::FromUtf8(new_str);
+ return *this;
+ }
+ String &operator=(const std::wstring &new_wstr)
+ {
+ this->utf8 = UtfConverter::ToUtf8(new_wstr);
+ this->ansi = DecodeFromUTF8(this->utf8, this->loc);
+ this->utf16 = new_wstr;
+ return *this;
+ }
+ String &operator=(const String &new_string)
+ {
+ if (this != &new_string)
+ {
+ this->ansi = new_string.ansi;
+ this->utf8 = new_string.utf8;
+ this->utf16 = new_string.utf16;
+ }
+ return *this;
+ }
+ String &SetISO8859_1(const std::string &new_str)
+ {
+ this->ansi = new_str;
+ this->utf8 = EncodeToUTF8(new_str, this->loc);
+ this->utf16 = UtfConverter::FromUtf8(this->utf8);
+ return *this;
+ }
+ String operator+(const String &str2) const
+ {
+ String new_string = String(*this);
+ new_string.ansi.append(str2.ansi);
+ new_string.utf8.append(str2.utf8);
+ new_string.utf16.append(str2.utf16);
+ return new_string;
+ }
+ String operator+(char chr) const
+ {
+ String new_string = String(*this);
+ char str2[] = { chr, 0 };
+ new_string.ansi.append(str2);
+ std::string new_utf8 = EncodeToUTF8(str2, this->loc);
+ new_string.utf8.append(new_utf8);
+ new_string.utf16.append(UtfConverter::FromUtf8(new_utf8));
+ return new_string;
+ }
+ String operator+(wchar_t wchr) const
+ {
+ String new_string = String(*this);
+ wchar_t wstr2[] = { wchr, 0 };
+ std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
+ new_string.ansi.append(DecodeFromUTF8(new_utf8, this->loc));
+ new_string.utf8.append(new_utf8);
+ new_string.utf16.append(wstr2);
+ return new_string;
+ }
+ String operator+(const char *str2) const
+ {
+ String new_string = String(*this);
+ new_string.ansi.append(DecodeFromUTF8(str2, this->loc));
+ new_string.utf8.append(str2);
+ new_string.utf16.append(UtfConverter::FromUtf8(str2));
+ return new_string;
+ }
+ String operator+(const std::string &str2) const
+ {
+ String new_string = String(*this);
+ new_string.ansi.append(DecodeFromUTF8(str2, this->loc));
+ new_string.utf8.append(str2);
+ new_string.utf16.append(UtfConverter::FromUtf8(str2));
+ return new_string;
+ }
+ String operator+(const wchar_t *wstr2) const
+ {
+ String new_string = String(*this);
+ std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
+ new_string.ansi.append(DecodeFromUTF8(new_utf8, this->loc));
+ new_string.utf8.append(new_utf8);
+ new_string.utf16.append(wstr2);
+ return new_string;
+ }
+ String operator+(const std::wstring &wstr2) const
+ {
+ String new_string = String(*this);
+ std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
+ new_string.ansi.append(DecodeFromUTF8(new_utf8, this->loc));
+ new_string.utf8.append(new_utf8);
+ new_string.utf16.append(wstr2);
+ return new_string;
+ }
+ String &operator+=(const String &str2)
+ {
+ if (this != &str2)
+ {
+ this->ansi.append(str2.ansi);
+ this->utf8.append(str2.utf8);
+ this->utf16.append(str2.utf16);
+ }
+ return *this;
+ }
+ String &operator+=(char chr)
+ {
+ char str2[] = { chr, 0 };
+ this->ansi.append(str2);
+ std::string new_utf8 = EncodeToUTF8(str2, this->loc);
+ this->utf8.append(new_utf8);
+ this->utf16.append(UtfConverter::FromUtf8(new_utf8));
+ return *this;
+ }
+ String &operator+=(wchar_t wchr)
+ {
+ wchar_t wstr2[] = { wchr, 0 };
+ std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
+ this->ansi.append(DecodeFromUTF8(new_utf8, this->loc));
+ this->utf8.append(new_utf8);
+ this->utf16.append(wstr2);
+ return *this;
+ }
+ String &operator+=(const char *str2)
+ {
+ this->ansi.append(DecodeFromUTF8(str2, this->loc));
+ this->utf8.append(str2);
+ this->utf16.append(UtfConverter::FromUtf8(str2));
+ return *this;
+ }
+ String &operator+=(const std::string &str2)
+ {
+ this->ansi.append(DecodeFromUTF8(str2, this->loc));
+ this->utf8.append(str2);
+ this->utf16.append(UtfConverter::FromUtf8(str2));
+ return *this;
+ }
+ String &operator+=(const wchar_t *wstr2)
+ {
+ std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
+ this->ansi.append(DecodeFromUTF8(new_utf8, this->loc));
+ this->utf8.append(new_utf8);
+ this->utf16.append(wstr2);
+ return *this;
+ }
+ String &operator+=(const std::wstring &wstr2)
+ {
+ std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
+ this->ansi.append(DecodeFromUTF8(new_utf8, this->loc));
+ this->utf8.append(new_utf8);
+ this->utf16.append(wstr2);
+ return *this;
+ }
+ String &AppendISO8859_1(const std::string &str2)
+ {
+ this->ansi.append(str2);
+ std::string new_utf8 = EncodeToUTF8(str2, this->loc);
+ this->utf8.append(new_utf8);
+ this->utf16.append(UtfConverter::FromUtf8(new_utf8));
+ return *this;
+ }
+ String Substring(size_t pos = 0, size_t n = std::string::npos) const
+ {
+ String new_string = String(*this);
+ new_string.ansi.substr(pos, n);
+ new_string.utf8.substr(pos, n);
+ if (n == std::string::npos)
+ n = std::wstring::npos;
+ new_string.utf16.substr(pos, n);
+ return new_string;
+ }
+ void CopyToString(wchar_t *str, bool = false) const
+ {
+ wcscpy(str, utf16.c_str());
+ }
+ void CopyToString(char *str, bool use_utf8 = false) const
+ {
+ strcpy(str, (use_utf8 ? utf8 : ansi).c_str());
+ }
+protected:
+ std::string ansi, utf8;
+ std::wstring utf16;
+ std::locale loc;
+};
+
+#endif
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/Channel.cpp b/Frameworks/SSEQPlayer/SSEQPlayer/Channel.cpp
new file mode 100644
index 000000000..70ab361fa
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/Channel.cpp
@@ -0,0 +1,772 @@
+/*
+ * SSEQ Player - Channel structures
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ * Last modification on 2013-04-23
+ *
+ * Adapted from source code of FeOS Sound System
+ * By fincs
+ * https://github.com/fincs/FSS
+ *
+ * Some code/concepts from DeSmuME
+ * http://desmume.org/
+ */
+
+#define _USE_MATH_DEFINES
+#include
+#include
+#include
+#include "Channel.h"
+#include "Player.h"
+#include "common.h"
+
+NDSSoundRegister::NDSSoundRegister() : volumeMul(0), volumeDiv(0), panning(0), waveDuty(0), repeatMode(0), format(0), enable(false),
+ source(nullptr), timer(0), psgX(0), psgLast(0), psgLastCount(0), samplePosition(0), sampleIncrease(0), loopStart(0), length(0), totalLength(0)
+{
+}
+
+void NDSSoundRegister::ClearControlRegister()
+{
+ this->volumeMul = this->volumeDiv = this->panning = this->waveDuty = this->repeatMode = this->format = 0;
+ this->enable = false;
+}
+
+void NDSSoundRegister::SetControlRegister(uint32_t reg)
+{
+ this->volumeMul = reg & 0x7F;
+ this->volumeDiv = (reg >> 8) & 0x03;
+ this->panning = (reg >> 16) & 0x7F;
+ this->waveDuty = (reg >> 24) & 0x07;
+ this->repeatMode = (reg >> 27) & 0x03;
+ this->format = (reg >> 29) & 0x03;
+ this->enable = (reg >> 31) & 0x01;
+}
+
+TempSndReg::TempSndReg() : CR(0), SOURCE(nullptr), TIMER(0), REPEAT_POINT(0), LENGTH(0)
+{
+}
+
+bool Channel::initializedLUTs = false;
+double Channel::cosine_lut[Channel::COSINE_RESOLUTION];
+double Channel::lanczos_lut[Channel::LANCZOS_SAMPLES + 1];
+
+#ifndef M_PI
+static const double M_PI = 3.14159265358979323846;
+#endif
+
+// Code from http://learningcppisfun.blogspot.com/2010/04/comparing-floating-point-numbers.html
+template inline bool fEqual(T x, T y, int N = 1)
+{
+ T diff = std::abs(x - y);
+ T tolerance = N * std::numeric_limits::epsilon();
+ return diff <= tolerance * std::abs(x) && diff <= tolerance * std::abs(y);
+}
+
+static inline double sinc(double x)
+{
+ return fEqual(x, 0.0) ? 1.0 : std::sin(x * M_PI) / (x * M_PI);
+}
+
+Channel::Channel() : chnId(-1), tempReg(), state(CS_NONE), trackId(-1), prio(0), manualSweep(false), flags(), pan(0), extAmpl(0), velocity(0), extPan(0),
+ key(0), ampl(0), extTune(0), orgKey(0), modType(0), modSpeed(0), modDepth(0), modRange(0), modDelay(0), modDelayCnt(0), modCounter(0),
+ sweepLen(0), sweepCnt(0), sweepPitch(0), attackLvl(0), sustainLvl(0x7F), decayRate(0), releaseRate(0xFFFF), noteLength(-1), vol(0), ply(nullptr), reg()
+{
+ this->clearHistory();
+ if (!this->initializedLUTs)
+ {
+ for (unsigned i = 0; i < COSINE_RESOLUTION; ++i)
+ this->cosine_lut[i] = (1.0 - std::cos((static_cast(i) / COSINE_RESOLUTION) * M_PI)) * 0.5;
+ double dx = static_cast(LANCZOS_WIDTH) / LANCZOS_SAMPLES, x = 0.0;
+ for (unsigned i = 0; i <= LANCZOS_SAMPLES; ++i, x += dx)
+ this->lanczos_lut[i] = std::abs(x) < LANCZOS_WIDTH ? sinc(x) * sinc(x / LANCZOS_WIDTH) : 0.0;
+ this->initializedLUTs = true;
+ }
+}
+
+void Channel::UpdateVol(const Track &trk)
+{
+ int finalVol = trk.ply->masterVol;
+ finalVol += Cnv_Sust(trk.vol);
+ finalVol += Cnv_Sust(trk.expr);
+ if (finalVol < -AMPL_K)
+ finalVol = -AMPL_K;
+ this->extAmpl = finalVol;
+}
+
+void Channel::UpdatePan(const Track &trk)
+{
+ this->extPan = trk.pan;
+}
+
+void Channel::UpdateTune(const Track &trk)
+{
+ int tune = (static_cast(this->key) - static_cast(this->orgKey)) * 64;
+ tune += (static_cast(trk.pitchBend) * static_cast(trk.pitchBendRange)) >> 1;
+ this->extTune = tune;
+}
+
+void Channel::UpdateMod(const Track &trk)
+{
+ this->modType = trk.modType;
+ this->modSpeed = trk.modSpeed;
+ this->modDepth = trk.modDepth;
+ this->modRange = trk.modRange;
+ this->modDelay = trk.modDelay;
+}
+
+void Channel::UpdatePorta(const Track &trk)
+{
+ this->manualSweep = false;
+ this->sweepPitch = trk.sweepPitch;
+ this->sweepCnt = 0;
+ if (!trk.state[TS_PORTABIT])
+ {
+ this->sweepLen = 0;
+ return;
+ }
+
+ int diff = (static_cast(trk.portaKey) - static_cast(this->key)) << 22;
+ this->sweepPitch += diff >> 16;
+
+ if (!trk.portaTime)
+ {
+ this->sweepLen = this->noteLength;
+ this->manualSweep = true;
+ }
+ else
+ {
+ int sq_time = static_cast(trk.portaTime) * static_cast(trk.portaTime);
+ long abs_sp = std::abs((long)this->sweepPitch);
+ this->sweepLen = (abs_sp * sq_time) >> 11;
+ }
+}
+
+void Channel::Release()
+{
+ this->noteLength = -1;
+ this->prio = 1;
+ this->state = CS_RELEASE;
+}
+
+void Channel::Kill()
+{
+ this->state = CS_NONE;
+ this->trackId = -1;
+ this->prio = 0;
+ this->reg.ClearControlRegister();
+ this->vol = 0;
+ this->noteLength = -1;
+ this->clearHistory();
+}
+
+static inline int getModFlag(int type)
+{
+ switch (type)
+ {
+ case 0:
+ return CF_UPDTMR;
+ case 1:
+ return CF_UPDVOL;
+ case 2:
+ return CF_UPDPAN;
+ default:
+ return 0;
+ }
+}
+
+void Channel::UpdateTrack()
+{
+ if (!this->ply)
+ return;
+
+ int trkn = this->trackId;
+ if (trkn == -1)
+ return;
+
+ auto &trackFlags = this->ply->tracks[trkn].updateFlags;
+ if (trackFlags.none())
+ return;
+
+ auto &trk = this->ply->tracks[trkn];
+ if (trackFlags[TUF_LEN])
+ {
+ int st = this->state;
+ if (st > CS_START)
+ {
+ if (st < CS_RELEASE && !--this->noteLength)
+ this->Release();
+ if (this->manualSweep && this->sweepCnt < this->sweepLen)
+ ++this->sweepCnt;
+ }
+ }
+ if (trackFlags[TUF_VOL])
+ {
+ this->UpdateVol(trk);
+ this->flags.set(CF_UPDVOL);
+ }
+ if (trackFlags[TUF_PAN])
+ {
+ this->UpdatePan(trk);
+ this->flags.set(CF_UPDPAN);
+ }
+ if (trackFlags[TUF_TIMER])
+ {
+ this->UpdateTune(trk);
+ this->flags.set(CF_UPDTMR);
+ }
+ if (trackFlags[TUF_MOD])
+ {
+ int oldType = this->modType;
+ int newType = trk.modType;
+ this->UpdateMod(trk);
+ if (oldType != newType)
+ {
+ this->flags.set(getModFlag(oldType));
+ this->flags.set(getModFlag(newType));
+ }
+ }
+}
+
+static const uint16_t getpitchtbl[] =
+{
+ 0x0000, 0x003B, 0x0076, 0x00B2, 0x00ED, 0x0128, 0x0164, 0x019F,
+ 0x01DB, 0x0217, 0x0252, 0x028E, 0x02CA, 0x0305, 0x0341, 0x037D,
+ 0x03B9, 0x03F5, 0x0431, 0x046E, 0x04AA, 0x04E6, 0x0522, 0x055F,
+ 0x059B, 0x05D8, 0x0614, 0x0651, 0x068D, 0x06CA, 0x0707, 0x0743,
+ 0x0780, 0x07BD, 0x07FA, 0x0837, 0x0874, 0x08B1, 0x08EF, 0x092C,
+ 0x0969, 0x09A7, 0x09E4, 0x0A21, 0x0A5F, 0x0A9C, 0x0ADA, 0x0B18,
+ 0x0B56, 0x0B93, 0x0BD1, 0x0C0F, 0x0C4D, 0x0C8B, 0x0CC9, 0x0D07,
+ 0x0D45, 0x0D84, 0x0DC2, 0x0E00, 0x0E3F, 0x0E7D, 0x0EBC, 0x0EFA,
+ 0x0F39, 0x0F78, 0x0FB6, 0x0FF5, 0x1034, 0x1073, 0x10B2, 0x10F1,
+ 0x1130, 0x116F, 0x11AE, 0x11EE, 0x122D, 0x126C, 0x12AC, 0x12EB,
+ 0x132B, 0x136B, 0x13AA, 0x13EA, 0x142A, 0x146A, 0x14A9, 0x14E9,
+ 0x1529, 0x1569, 0x15AA, 0x15EA, 0x162A, 0x166A, 0x16AB, 0x16EB,
+ 0x172C, 0x176C, 0x17AD, 0x17ED, 0x182E, 0x186F, 0x18B0, 0x18F0,
+ 0x1931, 0x1972, 0x19B3, 0x19F5, 0x1A36, 0x1A77, 0x1AB8, 0x1AFA,
+ 0x1B3B, 0x1B7D, 0x1BBE, 0x1C00, 0x1C41, 0x1C83, 0x1CC5, 0x1D07,
+ 0x1D48, 0x1D8A, 0x1DCC, 0x1E0E, 0x1E51, 0x1E93, 0x1ED5, 0x1F17,
+ 0x1F5A, 0x1F9C, 0x1FDF, 0x2021, 0x2064, 0x20A6, 0x20E9, 0x212C,
+ 0x216F, 0x21B2, 0x21F5, 0x2238, 0x227B, 0x22BE, 0x2301, 0x2344,
+ 0x2388, 0x23CB, 0x240E, 0x2452, 0x2496, 0x24D9, 0x251D, 0x2561,
+ 0x25A4, 0x25E8, 0x262C, 0x2670, 0x26B4, 0x26F8, 0x273D, 0x2781,
+ 0x27C5, 0x280A, 0x284E, 0x2892, 0x28D7, 0x291C, 0x2960, 0x29A5,
+ 0x29EA, 0x2A2F, 0x2A74, 0x2AB9, 0x2AFE, 0x2B43, 0x2B88, 0x2BCD,
+ 0x2C13, 0x2C58, 0x2C9D, 0x2CE3, 0x2D28, 0x2D6E, 0x2DB4, 0x2DF9,
+ 0x2E3F, 0x2E85, 0x2ECB, 0x2F11, 0x2F57, 0x2F9D, 0x2FE3, 0x302A,
+ 0x3070, 0x30B6, 0x30FD, 0x3143, 0x318A, 0x31D0, 0x3217, 0x325E,
+ 0x32A5, 0x32EC, 0x3332, 0x3379, 0x33C1, 0x3408, 0x344F, 0x3496,
+ 0x34DD, 0x3525, 0x356C, 0x35B4, 0x35FB, 0x3643, 0x368B, 0x36D3,
+ 0x371A, 0x3762, 0x37AA, 0x37F2, 0x383A, 0x3883, 0x38CB, 0x3913,
+ 0x395C, 0x39A4, 0x39ED, 0x3A35, 0x3A7E, 0x3AC6, 0x3B0F, 0x3B58,
+ 0x3BA1, 0x3BEA, 0x3C33, 0x3C7C, 0x3CC5, 0x3D0E, 0x3D58, 0x3DA1,
+ 0x3DEA, 0x3E34, 0x3E7D, 0x3EC7, 0x3F11, 0x3F5A, 0x3FA4, 0x3FEE,
+ 0x4038, 0x4082, 0x40CC, 0x4116, 0x4161, 0x41AB, 0x41F5, 0x4240,
+ 0x428A, 0x42D5, 0x431F, 0x436A, 0x43B5, 0x4400, 0x444B, 0x4495,
+ 0x44E1, 0x452C, 0x4577, 0x45C2, 0x460D, 0x4659, 0x46A4, 0x46F0,
+ 0x473B, 0x4787, 0x47D3, 0x481E, 0x486A, 0x48B6, 0x4902, 0x494E,
+ 0x499A, 0x49E6, 0x4A33, 0x4A7F, 0x4ACB, 0x4B18, 0x4B64, 0x4BB1,
+ 0x4BFE, 0x4C4A, 0x4C97, 0x4CE4, 0x4D31, 0x4D7E, 0x4DCB, 0x4E18,
+ 0x4E66, 0x4EB3, 0x4F00, 0x4F4E, 0x4F9B, 0x4FE9, 0x5036, 0x5084,
+ 0x50D2, 0x5120, 0x516E, 0x51BC, 0x520A, 0x5258, 0x52A6, 0x52F4,
+ 0x5343, 0x5391, 0x53E0, 0x542E, 0x547D, 0x54CC, 0x551A, 0x5569,
+ 0x55B8, 0x5607, 0x5656, 0x56A5, 0x56F4, 0x5744, 0x5793, 0x57E2,
+ 0x5832, 0x5882, 0x58D1, 0x5921, 0x5971, 0x59C1, 0x5A10, 0x5A60,
+ 0x5AB0, 0x5B01, 0x5B51, 0x5BA1, 0x5BF1, 0x5C42, 0x5C92, 0x5CE3,
+ 0x5D34, 0x5D84, 0x5DD5, 0x5E26, 0x5E77, 0x5EC8, 0x5F19, 0x5F6A,
+ 0x5FBB, 0x600D, 0x605E, 0x60B0, 0x6101, 0x6153, 0x61A4, 0x61F6,
+ 0x6248, 0x629A, 0x62EC, 0x633E, 0x6390, 0x63E2, 0x6434, 0x6487,
+ 0x64D9, 0x652C, 0x657E, 0x65D1, 0x6624, 0x6676, 0x66C9, 0x671C,
+ 0x676F, 0x67C2, 0x6815, 0x6869, 0x68BC, 0x690F, 0x6963, 0x69B6,
+ 0x6A0A, 0x6A5E, 0x6AB1, 0x6B05, 0x6B59, 0x6BAD, 0x6C01, 0x6C55,
+ 0x6CAA, 0x6CFE, 0x6D52, 0x6DA7, 0x6DFB, 0x6E50, 0x6EA4, 0x6EF9,
+ 0x6F4E, 0x6FA3, 0x6FF8, 0x704D, 0x70A2, 0x70F7, 0x714D, 0x71A2,
+ 0x71F7, 0x724D, 0x72A2, 0x72F8, 0x734E, 0x73A4, 0x73FA, 0x7450,
+ 0x74A6, 0x74FC, 0x7552, 0x75A8, 0x75FF, 0x7655, 0x76AC, 0x7702,
+ 0x7759, 0x77B0, 0x7807, 0x785E, 0x78B4, 0x790C, 0x7963, 0x79BA,
+ 0x7A11, 0x7A69, 0x7AC0, 0x7B18, 0x7B6F, 0x7BC7, 0x7C1F, 0x7C77,
+ 0x7CCF, 0x7D27, 0x7D7F, 0x7DD7, 0x7E2F, 0x7E88, 0x7EE0, 0x7F38,
+ 0x7F91, 0x7FEA, 0x8042, 0x809B, 0x80F4, 0x814D, 0x81A6, 0x81FF,
+ 0x8259, 0x82B2, 0x830B, 0x8365, 0x83BE, 0x8418, 0x8472, 0x84CB,
+ 0x8525, 0x857F, 0x85D9, 0x8633, 0x868E, 0x86E8, 0x8742, 0x879D,
+ 0x87F7, 0x8852, 0x88AC, 0x8907, 0x8962, 0x89BD, 0x8A18, 0x8A73,
+ 0x8ACE, 0x8B2A, 0x8B85, 0x8BE0, 0x8C3C, 0x8C97, 0x8CF3, 0x8D4F,
+ 0x8DAB, 0x8E07, 0x8E63, 0x8EBF, 0x8F1B, 0x8F77, 0x8FD4, 0x9030,
+ 0x908C, 0x90E9, 0x9146, 0x91A2, 0x91FF, 0x925C, 0x92B9, 0x9316,
+ 0x9373, 0x93D1, 0x942E, 0x948C, 0x94E9, 0x9547, 0x95A4, 0x9602,
+ 0x9660, 0x96BE, 0x971C, 0x977A, 0x97D8, 0x9836, 0x9895, 0x98F3,
+ 0x9952, 0x99B0, 0x9A0F, 0x9A6E, 0x9ACD, 0x9B2C, 0x9B8B, 0x9BEA,
+ 0x9C49, 0x9CA8, 0x9D08, 0x9D67, 0x9DC7, 0x9E26, 0x9E86, 0x9EE6,
+ 0x9F46, 0x9FA6, 0xA006, 0xA066, 0xA0C6, 0xA127, 0xA187, 0xA1E8,
+ 0xA248, 0xA2A9, 0xA30A, 0xA36B, 0xA3CC, 0xA42D, 0xA48E, 0xA4EF,
+ 0xA550, 0xA5B2, 0xA613, 0xA675, 0xA6D6, 0xA738, 0xA79A, 0xA7FC,
+ 0xA85E, 0xA8C0, 0xA922, 0xA984, 0xA9E7, 0xAA49, 0xAAAC, 0xAB0E,
+ 0xAB71, 0xABD4, 0xAC37, 0xAC9A, 0xACFD, 0xAD60, 0xADC3, 0xAE27,
+ 0xAE8A, 0xAEED, 0xAF51, 0xAFB5, 0xB019, 0xB07C, 0xB0E0, 0xB145,
+ 0xB1A9, 0xB20D, 0xB271, 0xB2D6, 0xB33A, 0xB39F, 0xB403, 0xB468,
+ 0xB4CD, 0xB532, 0xB597, 0xB5FC, 0xB662, 0xB6C7, 0xB72C, 0xB792,
+ 0xB7F7, 0xB85D, 0xB8C3, 0xB929, 0xB98F, 0xB9F5, 0xBA5B, 0xBAC1,
+ 0xBB28, 0xBB8E, 0xBBF5, 0xBC5B, 0xBCC2, 0xBD29, 0xBD90, 0xBDF7,
+ 0xBE5E, 0xBEC5, 0xBF2C, 0xBF94, 0xBFFB, 0xC063, 0xC0CA, 0xC132,
+ 0xC19A, 0xC202, 0xC26A, 0xC2D2, 0xC33A, 0xC3A2, 0xC40B, 0xC473,
+ 0xC4DC, 0xC544, 0xC5AD, 0xC616, 0xC67F, 0xC6E8, 0xC751, 0xC7BB,
+ 0xC824, 0xC88D, 0xC8F7, 0xC960, 0xC9CA, 0xCA34, 0xCA9E, 0xCB08,
+ 0xCB72, 0xCBDC, 0xCC47, 0xCCB1, 0xCD1B, 0xCD86, 0xCDF1, 0xCE5B,
+ 0xCEC6, 0xCF31, 0xCF9C, 0xD008, 0xD073, 0xD0DE, 0xD14A, 0xD1B5,
+ 0xD221, 0xD28D, 0xD2F8, 0xD364, 0xD3D0, 0xD43D, 0xD4A9, 0xD515,
+ 0xD582, 0xD5EE, 0xD65B, 0xD6C7, 0xD734, 0xD7A1, 0xD80E, 0xD87B,
+ 0xD8E9, 0xD956, 0xD9C3, 0xDA31, 0xDA9E, 0xDB0C, 0xDB7A, 0xDBE8,
+ 0xDC56, 0xDCC4, 0xDD32, 0xDDA0, 0xDE0F, 0xDE7D, 0xDEEC, 0xDF5B,
+ 0xDFC9, 0xE038, 0xE0A7, 0xE116, 0xE186, 0xE1F5, 0xE264, 0xE2D4,
+ 0xE343, 0xE3B3, 0xE423, 0xE493, 0xE503, 0xE573, 0xE5E3, 0xE654,
+ 0xE6C4, 0xE735, 0xE7A5, 0xE816, 0xE887, 0xE8F8, 0xE969, 0xE9DA,
+ 0xEA4B, 0xEABC, 0xEB2E, 0xEB9F, 0xEC11, 0xEC83, 0xECF5, 0xED66,
+ 0xEDD9, 0xEE4B, 0xEEBD, 0xEF2F, 0xEFA2, 0xF014, 0xF087, 0xF0FA,
+ 0xF16D, 0xF1E0, 0xF253, 0xF2C6, 0xF339, 0xF3AD, 0xF420, 0xF494,
+ 0xF507, 0xF57B, 0xF5EF, 0xF663, 0xF6D7, 0xF74C, 0xF7C0, 0xF834,
+ 0xF8A9, 0xF91E, 0xF992, 0xFA07, 0xFA7C, 0xFAF1, 0xFB66, 0xFBDC,
+ 0xFC51, 0xFCC7, 0xFD3C, 0xFDB2, 0xFE28, 0xFE9E, 0xFF14, 0xFF8A
+};
+
+static const uint8_t getvoltbl[] =
+{
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
+ 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E,
+ 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x18,
+ 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C,
+ 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22,
+ 0x22, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x29,
+ 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x31, 0x31,
+ 0x32, 0x32, 0x33, 0x33, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x38, 0x38, 0x39, 0x3A, 0x3A, 0x3B,
+ 0x3C, 0x3C, 0x3D, 0x3E, 0x3F, 0x3F, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x52, 0x53, 0x54, 0x55,
+ 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67,
+ 0x68, 0x69, 0x6A, 0x6B, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, 0x7B,
+ 0x7D, 0x7E, 0x7F, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25,
+ 0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D,
+ 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x36,
+ 0x36, 0x37, 0x37, 0x38, 0x39, 0x39, 0x3A, 0x3B, 0x3B, 0x3C, 0x3D, 0x3E, 0x3E, 0x3F, 0x40, 0x40,
+ 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D,
+ 0x5E, 0x5F, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6F, 0x70,
+ 0x71, 0x73, 0x74, 0x75, 0x77, 0x78, 0x79, 0x7B, 0x7C, 0x7E, 0x7E, 0x40, 0x41, 0x42, 0x43, 0x43,
+ 0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
+ 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61,
+ 0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, 0x6E, 0x70, 0x71, 0x72, 0x74, 0x75,
+ 0x76, 0x78, 0x79, 0x7B, 0x7C, 0x7D, 0x7E, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x46, 0x46,
+ 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
+ 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A,
+ 0x7C, 0x7D, 0x7E, 0x7F
+};
+
+// This function was obtained through disassembly of Ninty's sound driver
+static inline uint16_t Timer_Adjust(uint16_t basetmr, int pitch)
+{
+ int shift = 0;
+ pitch = -pitch;
+
+ while (pitch < 0)
+ {
+ --shift;
+ pitch += 0x300;
+ }
+
+ while (pitch >= 0x300)
+ {
+ ++shift;
+ pitch -= 0x300;
+ }
+
+ uint64_t tmr = static_cast(basetmr) * (static_cast(getpitchtbl[pitch]) + 0x10000);
+ shift -= 16;
+ if (shift <= 0)
+ tmr >>= -shift;
+ else if (shift < 32)
+ {
+ if (tmr & ((~0ULL) << (32 - shift)))
+ return 0xFFFF;
+ tmr <<= shift;
+ }
+ else
+ return 0x10;
+
+ if (tmr < 0x10)
+ return 0x10;
+ if (tmr > 0xFFFF)
+ return 0xFFFF;
+ return static_cast(tmr);
+}
+
+static inline int calcVolDivShift(int x)
+{
+ // VOLDIV(0) /1 >>0
+ // VOLDIV(1) /2 >>1
+ // VOLDIV(2) /4 >>2
+ // VOLDIV(3) /16 >>4
+ if (x < 3)
+ return x;
+ return 4;
+}
+
+void Channel::Update()
+{
+ // Kill active channels that aren't physically active
+ if (this->state > CS_START && !this->reg.enable)
+ {
+ this->Kill();
+ return;
+ }
+
+ bool bNotInSustain = this->state != CS_SUSTAIN;
+ bool bInStart = this->state == CS_START;
+ bool bPitchSweep = this->sweepPitch && this->sweepLen && this->sweepCnt <= this->sweepLen;
+ bool bModulation = !!this->modDepth;
+ bool bVolNeedUpdate = this->flags[CF_UPDVOL] || bNotInSustain;
+ bool bPanNeedUpdate = this->flags[CF_UPDPAN] || bInStart;
+ bool bTmrNeedUpdate = this->flags[CF_UPDTMR] || bInStart || bPitchSweep;
+ int modParam = 0;
+
+ switch (this->state)
+ {
+ case CS_NONE:
+ return;
+ case CS_START:
+ this->reg.ClearControlRegister();
+ this->reg.source = this->tempReg.SOURCE;
+ this->reg.loopStart = this->tempReg.REPEAT_POINT;
+ this->reg.length = this->tempReg.LENGTH;
+ this->reg.totalLength = this->reg.loopStart + this->reg.length;
+ this->ampl = AMPL_THRESHOLD;
+ this->state = CS_ATTACK;
+ // Fall down
+ case CS_ATTACK:
+ this->ampl = (static_cast(this->ampl) * static_cast(this->attackLvl)) / 255;
+ if (!this->ampl)
+ this->state = CS_DECAY;
+ break;
+ case CS_DECAY:
+ {
+ this->ampl -= static_cast(this->decayRate);
+ int sustLvl = Cnv_Sust(this->sustainLvl) << 7;
+ if (this->ampl <= sustLvl)
+ {
+ this->ampl = sustLvl;
+ this->state = CS_SUSTAIN;
+ }
+ break;
+ }
+ case CS_RELEASE:
+ this->ampl -= static_cast(this->releaseRate);
+ if (this->ampl > AMPL_THRESHOLD)
+ break;
+ this->Kill();
+ return;
+ }
+
+ if (bModulation && this->modDelayCnt < this->modDelay)
+ {
+ ++this->modDelayCnt;
+ bModulation = false;
+ }
+
+ if (bModulation)
+ {
+ switch (this->modType)
+ {
+ case 0:
+ bTmrNeedUpdate = true;
+ break;
+ case 1:
+ bVolNeedUpdate = true;
+ break;
+ case 2:
+ bPanNeedUpdate = true;
+ }
+
+ // Get the current modulation parameter
+ modParam = Cnv_Sine(this->modCounter >> 8) * this->modRange * this->modDepth;
+
+ if (!this->modType)
+ modParam = static_cast(modParam * 60) >> 14;
+ else
+ // This ugly formula whose exact meaning and workings I cannot figure out is used for volume/pan modulation.
+ modParam = ((modParam & ~0xFC000000) >> 8) | ((((modParam < 0 ? -1 : 0) << 6) | (static_cast(modParam) >> 26)) << 18);
+
+ // Update the modulation variables
+
+ uint16_t speed = static_cast(this->modSpeed) << 6;
+ uint16_t counter = (this->modCounter + speed) >> 8;
+
+ while (counter >= 0x80)
+ counter -= 0x80;
+
+ this->modCounter += speed;
+ this->modCounter &= 0xFF;
+ this->modCounter |= counter << 8;
+ }
+
+ if (bTmrNeedUpdate)
+ {
+ int totalAdj = this->extTune;
+ if (bModulation && !this->modType)
+ totalAdj += modParam;
+ if (bPitchSweep)
+ {
+ int len = this->sweepLen;
+ int cnt = this->sweepCnt;
+ totalAdj += (static_cast(this->sweepPitch) * (len - cnt)) / len;
+ if (!this->manualSweep)
+ ++this->sweepCnt;
+ }
+ uint16_t tmr = this->tempReg.TIMER;
+
+ if (totalAdj)
+ tmr = Timer_Adjust(tmr, totalAdj);
+ this->reg.timer = -tmr;
+ this->reg.sampleIncrease = (ARM7_CLOCK / static_cast(this->ply->sampleRate * 2)) / (0x10000 - this->reg.timer);
+ this->flags.reset(CF_UPDTMR);
+ }
+
+ if (bVolNeedUpdate || bPanNeedUpdate)
+ {
+ uint32_t cr = this->tempReg.CR;
+ if (bVolNeedUpdate)
+ {
+ int totalVol = this->ampl >> 7;
+ totalVol += this->extAmpl;
+ totalVol += this->velocity;
+ if (bModulation && this->modType == 1)
+ totalVol += modParam;
+ totalVol += AMPL_K;
+ if (totalVol < 0)
+ totalVol = 0;
+
+ cr &= ~(SOUND_VOL(0x7F) | SOUND_VOLDIV(3));
+ cr |= SOUND_VOL(static_cast(getvoltbl[totalVol]));
+
+ if (totalVol < AMPL_K - 240)
+ cr |= SOUND_VOLDIV(3);
+ else if (totalVol < AMPL_K - 120)
+ cr |= SOUND_VOLDIV(2);
+ else if (totalVol < AMPL_K - 60)
+ cr |= SOUND_VOLDIV(1);
+
+ this->vol = ((cr & SOUND_VOL(0x7F)) << 4) >> calcVolDivShift((cr & SOUND_VOLDIV(3)) >> 8);
+
+ this->flags.reset(CF_UPDVOL);
+ }
+
+ if (bPanNeedUpdate)
+ {
+ int realPan = this->pan;
+ realPan += this->extPan;
+ if (bModulation && this->modType == 2)
+ realPan += modParam;
+ realPan += 64;
+ if (realPan < 0)
+ realPan = 0;
+ else if (realPan > 127)
+ realPan = 127;
+
+ cr &= ~SOUND_PAN(0x7F);
+ cr |= SOUND_PAN(realPan);
+ this->flags.reset(CF_UPDPAN);
+ }
+
+ this->tempReg.CR = cr;
+ this->reg.SetControlRegister(cr);
+ }
+}
+
+static const int16_t wavedutytbl[8][8] =
+{
+ { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF },
+ { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF },
+ { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF },
+ { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF },
+ { -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF },
+ { -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF },
+ { -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF },
+ { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF }
+};
+
+// Linear and Cosine interpolation code originally from DeSmuME
+// B-spline and Osculating come from Olli Niemitalo:
+// http://www.student.oulu.fi/~oniemita/dsp/deip.pdf
+int32_t Channel::Interpolate()
+{
+ double ratio = this->reg.samplePosition;
+ ratio -= static_cast(ratio);
+
+ const auto &data = &this->sampleHistory[this->sampleHistoryPtr + 16];
+
+ if (this->ply->interpolation == INTERPOLATION_LANCZOS)
+ {
+ double kernel[LANCZOS_WIDTH * 2], kernel_sum = 0.0;
+ int i = LANCZOS_WIDTH, shift = static_cast(std::floor(ratio * LANCZOS_RESOLUTION));
+ int step = this->reg.sampleIncrease > 1.0 ? static_cast((1.0 / this->reg.sampleIncrease) * LANCZOS_RESOLUTION) : LANCZOS_RESOLUTION;
+ long shift_adj = shift * step / LANCZOS_RESOLUTION;
+ for (; i >= -static_cast(LANCZOS_WIDTH - 1); --i)
+ {
+ long pos = i * step;
+ kernel_sum += kernel[i + LANCZOS_WIDTH - 1] = this->lanczos_lut[std::abs(shift_adj - pos)];
+ }
+ double sum = 0.0;
+ for (i = 0; i < static_cast(LANCZOS_WIDTH * 2); ++i)
+ sum += data[i - static_cast(LANCZOS_WIDTH) + 1] * kernel[i];
+ return static_cast(sum / kernel_sum);
+ }
+ else if (this->ply->interpolation > INTERPOLATION_COSINE)
+ {
+ double c0, c1, c2, c3, c4, c5;
+
+ if (this->ply->interpolation > INTERPOLATION_4POINTBSPLINE)
+ {
+ if (this->ply->interpolation == INTERPOLATION_6POINTBSPLINE)
+ {
+ double ym2py2 = data[-2] + data[2], ym1py1 = data[-1] + data[1];
+ double y2mym2 = data[2] - data[-2], y1mym1 = data[1] - data[-1];
+ double sixthym1py1 = 1 / 6.0 * ym1py1;
+ c0 = 1 / 120.0 * ym2py2 + 13 / 60.0 * ym1py1 + 0.55 * data[0];
+ c1 = 1 / 24.0 * y2mym2 + 5 / 12.0 * y1mym1;
+ c2 = 1 / 12.0 * ym2py2 + sixthym1py1 - 0.5 * data[0];
+ c3 = 1 / 12.0 * y2mym2 - 1 / 6.0 * y1mym1;
+ c4 = 1 / 24.0 * ym2py2 - sixthym1py1 + 0.25 * data[0];
+ c5 = 1 / 120.0 * (data[3] - data[-2]) + 1 / 24.0 * (data[-1] - data[2]) + 1 / 12.0 * (data[1] - data[0]);
+ return static_cast(((((c5 * ratio + c4) * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0);
+ }
+ else // INTERPOLATION_6POINTOSCULATING
+ {
+ ratio -= 0.5;
+ double even1 = data[-2] + data[3], odd1 = data[-2] - data[3];
+ double even2 = data[-1] + data[2], odd2 = data[-1] - data[2];
+ double even3 = data[0] + data[1], odd3 = data[0] - data[1];
+ c0 = 0.01171875 * even1 - 0.09765625 * even2 + 0.5859375 * even3;
+ c1 = 0.2109375 * odd2 - 281 / 192.0 * odd3 - 13 / 384.0 * odd1;
+ c2 = 0.40625 * even2 - 17 / 48.0 * even3 - 5 / 96.0 * even1;
+ c3 = 0.1875 * odd1 - 53 / 48.0 * odd2 + 2.375 * odd3;
+ c4 = 1 / 48.0 * even1 - 0.0625 * even2 + 1 / 24.0 * even3;
+ c5 = 25 / 24.0 * odd2 - 25 / 12.0 * odd3 - 5 / 24.0 * odd1;
+ return static_cast(((((c5 * ratio + c4) * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0);
+ }
+ }
+ else // INTERPOLATION_4POINTBSPLINE
+ {
+ double ym1py1 = data[-1] + data[1];
+ c0 = 1 / 6.0 * ym1py1 + 2 / 3.0 * data[0];
+ c1 = 0.5 * (data[1] - data[-1]);
+ c2 = 0.5 * ym1py1 - data[0];
+ c3 = 0.5 * (data[0] - data[1]) + 1 / 6.0 * (data[2] - data[-1]);
+ return static_cast(((c3 * ratio + c2) * ratio + c1) * ratio + c0);
+ }
+ }
+ else if (this->ply->interpolation == INTERPOLATION_COSINE)
+ return static_cast(data[0] + this->cosine_lut[static_cast(ratio * COSINE_RESOLUTION)] * (data[1] - data[0]));
+ else // INTERPOLATION_LINEAR
+ return static_cast(data[0] + ratio * (data[1] - data[0]));
+}
+
+int32_t Channel::GenerateSample()
+{
+ if (this->reg.samplePosition < 0)
+ return 0;
+
+ if (this->reg.format != 3)
+ {
+ if (this->ply->interpolation == INTERPOLATION_NONE)
+ return this->reg.source->dataptr[static_cast(this->reg.samplePosition)];
+ else
+ return this->Interpolate();
+ }
+ else
+ {
+ if (this->chnId < 8)
+ return 0;
+ else if (this->chnId < 14)
+ return wavedutytbl[this->reg.waveDuty][static_cast(this->reg.samplePosition) & 0x7];
+ else
+ {
+ if (this->reg.psgLastCount != static_cast(this->reg.samplePosition))
+ {
+ uint32_t max = static_cast(this->reg.samplePosition);
+ for (uint32_t i = this->reg.psgLastCount; i < max; ++i)
+ {
+ if (this->reg.psgX & 0x1)
+ {
+ this->reg.psgX = (this->reg.psgX >> 1) ^ 0x6000;
+ this->reg.psgLast = -0x7FFF;
+ }
+ else
+ {
+ this->reg.psgX >>= 1;
+ this->reg.psgLast = 0x7FFF;
+ }
+ }
+
+ this->reg.psgLastCount = static_cast(this->reg.samplePosition);
+ }
+
+ return this->reg.psgLast;
+ }
+ }
+}
+
+void Channel::IncrementSample()
+{
+ double samplePosition = this->reg.samplePosition + this->reg.sampleIncrease;
+
+ if (this->reg.format != 3 && this->reg.samplePosition >= 0)
+ {
+ uint32_t loc = static_cast(this->reg.samplePosition);
+ uint32_t newloc = static_cast(samplePosition);
+
+ if (newloc >= this->reg.totalLength)
+ newloc -= this->reg.length;
+
+ while (loc != newloc)
+ {
+ this->sampleHistory[this->sampleHistoryPtr] = this->sampleHistory[this->sampleHistoryPtr + 32] = this->reg.source->dataptr[loc++];
+
+ this->sampleHistoryPtr = (this->sampleHistoryPtr + 1) & 31;
+
+ if (loc >= this->reg.totalLength)
+ loc -= this->reg.length;
+ }
+ }
+
+ this->reg.samplePosition = samplePosition;
+
+ if (this->reg.format != 3 && this->reg.samplePosition >= this->reg.totalLength)
+ {
+ if (this->reg.repeatMode == 1)
+ {
+ while (this->reg.samplePosition >= this->reg.totalLength)
+ this->reg.samplePosition -= this->reg.length;
+ }
+ else
+ this->Kill();
+ }
+}
+
+void Channel::clearHistory()
+{
+ this->sampleHistoryPtr = 0;
+ memset(this->sampleHistory, 0, sizeof(this->sampleHistory));
+}
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/Channel.h b/Frameworks/SSEQPlayer/SSEQPlayer/Channel.h
new file mode 100644
index 000000000..0a116fec7
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/Channel.h
@@ -0,0 +1,169 @@
+/*
+ * SSEQ Player - Channel structures
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ * Last modification on 2013-04-02
+ *
+ * Adapted from source code of FeOS Sound System
+ * By fincs
+ * https://github.com/fincs/FSS
+ *
+ * Some code/concepts from DeSmuME
+ * http://desmume.org/
+ */
+
+#ifndef SSEQPLAYER_CHANNEL_H
+#define SSEQPLAYER_CHANNEL_H
+
+#include
+#include
+#include
+#include "SWAV.h"
+#include "Track.h"
+
+/*
+ * This structure is meant to be similar to what is stored in the actual
+ * Nintendo DS's sound registers. Items that were not being used by this
+ * player have been removed, and items which help the simulated registers
+ * have been added.
+ */
+struct NDSSoundRegister
+{
+ // Control Register
+ uint8_t volumeMul;
+ uint8_t volumeDiv;
+ uint8_t panning;
+ uint8_t waveDuty;
+ uint8_t repeatMode;
+ uint8_t format;
+ bool enable;
+
+ // Data Source Register
+ const SWAV *source;
+
+ // Timer Register
+ uint16_t timer;
+
+ // PSG Handling, not a DS register
+ uint16_t psgX;
+ int16_t psgLast;
+ uint32_t psgLastCount;
+
+ // The following are taken from DeSmuME
+ double samplePosition;
+ double sampleIncrease;
+
+ // Loopstart Register
+ uint32_t loopStart;
+
+ // Length Register
+ uint32_t length;
+
+ uint32_t totalLength;
+
+ NDSSoundRegister();
+
+ void ClearControlRegister();
+ void SetControlRegister(uint32_t reg);
+};
+
+/*
+ * From FeOS Sound System, this is temporary storage of what will go into
+ * the Nintendo DS sound registers. It is kept separate as the original code
+ * from FeOS Sound System utilized this to hold data prior to passing it into
+ * the DS's registers.
+ */
+struct TempSndReg
+{
+ uint32_t CR;
+ const SWAV *SOURCE;
+ uint16_t TIMER;
+ uint32_t REPEAT_POINT, LENGTH;
+
+ TempSndReg();
+};
+
+struct Player;
+
+struct Channel
+{
+ int8_t chnId;
+
+ TempSndReg tempReg;
+ uint8_t state;
+ int8_t trackId; // -1 = none
+ uint8_t prio;
+ bool manualSweep;
+
+ std::bitset flags;
+ int8_t pan; // -64 .. 63
+ int16_t extAmpl;
+
+ int16_t velocity;
+ int8_t extPan;
+ uint8_t key;
+
+ int ampl; // 7 fractionary bits
+ int extTune; // in 64ths of a semitone
+
+ uint8_t orgKey;
+
+ uint8_t modType, modSpeed, modDepth, modRange;
+ uint16_t modDelay, modDelayCnt, modCounter;
+
+ uint32_t sweepLen, sweepCnt;
+ int16_t sweepPitch;
+
+ uint8_t attackLvl, sustainLvl;
+ uint16_t decayRate, releaseRate;
+
+ /*
+ * These were originally global variables in FeOS Sound System, but
+ * since they were linked to a certain channel anyways, I moved them
+ * into this class.
+ */
+ int noteLength;
+ uint16_t vol;
+
+ const Player *ply;
+ NDSSoundRegister reg;
+
+ /*
+ * Interpolation history buffer, which contains the maximum number of
+ * samples required for any given interpolation mode. Doubled to
+ * simplify the case of wrapping. Thanks to kode54 for providing this.
+ */
+ uint32_t sampleHistoryPtr;
+ int16_t sampleHistory[64];
+
+ /*
+ * Lookup tables for the cosine and Lanczos Sinc interpolations, to
+ * avoid the need to call the sin/cos functions all the time.
+ * These are static as they will not change between channels or runs
+ * of the program.
+ */
+ static bool initializedLUTs;
+ static const unsigned COSINE_RESOLUTION = 8192;
+ static const unsigned LANCZOS_RESOLUTION = 8192;
+ static const unsigned LANCZOS_WIDTH = 8;
+ static const unsigned LANCZOS_SAMPLES = LANCZOS_RESOLUTION * LANCZOS_WIDTH;
+ static double cosine_lut[COSINE_RESOLUTION];
+ static double lanczos_lut[LANCZOS_SAMPLES + 1];
+
+ Channel();
+
+ void UpdateVol(const Track &trk);
+ void UpdatePan(const Track &trk);
+ void UpdateTune(const Track &trk);
+ void UpdateMod(const Track &trk);
+ void UpdatePorta(const Track &trk);
+ void Release();
+ void Kill();
+ void UpdateTrack();
+ void Update();
+ int32_t Interpolate();
+ int32_t GenerateSample();
+ void IncrementSample();
+ void clearHistory();
+};
+
+#endif
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/ConvertUTF.cpp b/Frameworks/SSEQPlayer/SSEQPlayer/ConvertUTF.cpp
new file mode 100644
index 000000000..747f447b5
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/ConvertUTF.cpp
@@ -0,0 +1,602 @@
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* ---------------------------------------------------------------------
+
+ Conversions between UTF32, UTF-16, and UTF-8. Source code file.
+ Author: Mark E. Davis, 1994.
+ Rev History: Rick McGowan, fixes & updates May 2001.
+ Sept 2001: fixed const & error conditions per
+ mods suggested by S. Parent & A. Lillich.
+ June 2002: Tim Dodd added detection and handling of incomplete
+ source sequences, enhanced error detection, added casts
+ to eliminate compiler warnings.
+ July 2003: slight mods to back out aggressive FFFE detection.
+ Jan 2004: updated switches in from-UTF8 conversions.
+ Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
+
+ See the header file "ConvertUTF.h" for complete documentation.
+
+------------------------------------------------------------------------ */
+
+#include "ConvertUTF.h"
+
+static const int halfShift = 10; /* used for shifting by 10 bits */
+
+static const UTF32 halfBase = 0x0010000UL;
+static const UTF32 halfMask = 0x3FFUL;
+
+static const UTF32 UNI_SUR_HIGH_START = 0xD800;
+static const UTF32 UNI_SUR_HIGH_END = 0xDBFF;
+static const UTF32 UNI_SUR_LOW_START = 0xDC00;
+static const UTF32 UNI_SUR_LOW_END = 0xDFFF;
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF16(const UTF32 **sourceStart, const UTF32 *sourceEnd, UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF32 *source = *sourceStart;
+ UTF16 *target = *targetStart;
+ while (source < sourceEnd)
+ {
+ if (target >= targetEnd)
+ {
+ result = targetExhausted;
+ break;
+ }
+ UTF32 ch = *source++;
+ if (ch <= UNI_MAX_BMP) /* Target is a character <= 0xFFFF */
+ {
+ /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
+ {
+ if (flags == strictConversion)
+ {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ else
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ else
+ *target++ = static_cast(ch); /* normal case */
+ }
+ else if (ch > UNI_MAX_LEGAL_UTF32)
+ {
+ if (flags == strictConversion)
+ result = sourceIllegal;
+ else
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ else
+ {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd)
+ {
+ --source; /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ ch -= halfBase;
+ *target++ = static_cast((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = static_cast((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF32(const UTF16 **sourceStart, const UTF16 *sourceEnd, UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF16 *source = *sourceStart;
+ UTF32 *target = *targetStart;
+ while (source < sourceEnd)
+ {
+ const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */
+ UTF32 ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END)
+ {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd)
+ {
+ UTF32 ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END)
+ {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ }
+ else if (flags == strictConversion) /* it's an unpaired high surrogate */
+ {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ else /* We don't have the 16 bits following the high surrogate. */
+ {
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ }
+ else if (flags == strictConversion)
+ {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)
+ {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ if (target >= targetEnd)
+ {
+ source = oldSource; /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ *target++ = ch;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Index into the table below with the first byte of a UTF-8 sequence to
+ * get the number of trailing bytes that are supposed to follow it.
+ * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
+ * left as-is for anyone who may want to do such conversion, which was
+ * allowed in earlier algorithms.
+ */
+static const char trailingBytesForUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+/*
+ * Magic values subtracted from a buffer value during UTF8 conversion.
+ * This table contains as many values as there might be trailing bytes
+ * in a UTF-8 sequence.
+ */
+static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+
+/*
+ * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+ * into the first byte, depending on how many bytes follow. There are
+ * as many entries in this table as there are UTF-8 sequence types.
+ * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
+ * for *legal* UTF-8 will be 4 or fewer bytes total.
+ */
+static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+/* --------------------------------------------------------------------- */
+
+/* The interface converts a whole buffer to avoid function-call overhead.
+ * Constants have been gathered. Loops & conditionals have been removed as
+ * much as possible for efficiency, in favor of drop-through switches.
+ * (See "Note A" at the bottom of the file for equivalent code.)
+ * If your compiler supports it, the "isLegalUTF8" call can be turned
+ * into an inline function.
+ */
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF8(const UTF16 **sourceStart, const UTF16 *sourceEnd, UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF16 *source = *sourceStart;
+ UTF8 *target = *targetStart;
+ while (source < sourceEnd)
+ {
+ const UTF32 byteMask = 0xBF, byteMark = 0x80;
+ const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */
+ UTF32 ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END)
+ {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd)
+ {
+ UTF32 ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END)
+ {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ }
+ else if (flags == strictConversion) /* it's an unpaired high surrogate */
+ {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ else /* We don't have the 16 bits following the high surrogate. */
+ {
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ }
+ else if (flags == strictConversion)
+ {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)
+ {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /* Figure out how many bytes the result will require */
+ unsigned short bytesToWrite = 0;
+ if (ch < 0x80)
+ bytesToWrite = 1;
+ else if (ch < 0x800)
+ bytesToWrite = 2;
+ else if (ch < 0x10000)
+ bytesToWrite = 3;
+ else if (ch < 0x110000)
+ bytesToWrite = 4;
+ else
+ {
+ bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
+ target += bytesToWrite;
+ if (target > targetEnd)
+ {
+ source = oldSource; /* Back up source pointer! */
+ target -= bytesToWrite;
+ result = targetExhausted;
+ break;
+ }
+ switch (bytesToWrite) /* note: everything falls through. */
+ {
+ case 4: *--target = static_cast((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = static_cast((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = static_cast((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = static_cast(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Utility routine to tell whether a sequence of bytes is legal UTF-8.
+ * This must be called with the length pre-determined by the first byte.
+ * If not calling this from ConvertUTF8to*, then the length can be set by:
+ * length = trailingBytesForUTF8[*source]+1;
+ * and the sequence is illegal right away if there aren't that many bytes
+ * available.
+ * If presented with a length > 4, this returns false. The Unicode
+ * definition of UTF-8 goes up to 4-byte sequences.
+ */
+
+static bool isLegalUTF8(const UTF8 *source, int length)
+{
+ const UTF8 *srcptr = source + length;
+ UTF8 a;
+ switch (length)
+ {
+ default: return false;
+ /* Everything else falls through when "true"... */
+ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 2: if ((a = (*--srcptr)) > 0xBF) return false;
+
+ switch (*source)
+ {
+ /* no fall-through in this inner switch */
+ case 0xE0: if (a < 0xA0) return false; break;
+ case 0xED: if (a > 0x9F) return false; break;
+ case 0xF0: if (a < 0x90) return false; break;
+ case 0xF4: if (a > 0x8F) return false; break;
+ default: if (a < 0x80) return false;
+ }
+
+ case 1: if (*source >= 0x80 && *source < 0xC2) return false;
+ }
+ if (*source > 0xF4)
+ return false;
+ return true;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Exported function to return whether a UTF-8 sequence is legal or not.
+ * This is not used here; it's just exported.
+ */
+bool isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd)
+{
+ int length = trailingBytesForUTF8[*source] + 1;
+ if (source + length > sourceEnd)
+ return false;
+ return isLegalUTF8(source, length);
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF16(const UTF8 **sourceStart, const UTF8 *sourceEnd, UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF8 *source = *sourceStart;
+ UTF16 *target = *targetStart;
+ while (source < sourceEnd)
+ {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd)
+ {
+ result = sourceExhausted;
+ break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead + 1))
+ {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead)
+ {
+ case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd)
+ {
+ source -= extraBytesToRead + 1; /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ if (ch <= UNI_MAX_BMP) /* Target is a character <= 0xFFFF */
+ {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
+ {
+ if (flags == strictConversion)
+ {
+ source -= extraBytesToRead + 1; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ else
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ else
+ *target++ = static_cast(ch); /* normal case */
+ }
+ else if (ch > UNI_MAX_UTF16)
+ {
+ if (flags == strictConversion)
+ {
+ result = sourceIllegal;
+ source -= extraBytesToRead + 1; /* return to the start */
+ break; /* Bail out; shouldn't continue */
+ }
+ else
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ else
+ {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd)
+ {
+ source -= extraBytesToRead + 1; /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ ch -= halfBase;
+ *target++ = static_cast((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = static_cast((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF8(const UTF32 **sourceStart, const UTF32 *sourceEnd, UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF32 *source = *sourceStart;
+ UTF8 *target = *targetStart;
+ while (source < sourceEnd)
+ {
+ const UTF32 byteMask = 0xBF, byteMark = 0x80;
+ UTF32 ch = *source++;
+ if (flags == strictConversion)
+ {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
+ {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /*
+ * Figure out how many bytes the result will require. Turn any
+ * illegally large UTF32 things (> Plane 17) into replacement chars.
+ */
+ unsigned short bytesToWrite = 0;
+ if (ch < 0x80)
+ bytesToWrite = 1;
+ else if (ch < 0x800)
+ bytesToWrite = 2;
+ else if (ch < 0x10000)
+ bytesToWrite = 3;
+ else if (ch <= UNI_MAX_LEGAL_UTF32)
+ bytesToWrite = 4;
+ else
+ {
+ bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ result = sourceIllegal;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd)
+ {
+ --source; /* Back up source pointer! */
+ target -= bytesToWrite;
+ result = targetExhausted;
+ break;
+ }
+ switch (bytesToWrite) /* note: everything falls through. */
+ {
+ case 4: *--target = static_cast((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = static_cast((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = static_cast((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = static_cast(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, const UTF8 *sourceEnd, UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF8 *source = *sourceStart;
+ UTF32 *target = *targetStart;
+ while (source < sourceEnd)
+ {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd)
+ {
+ result = sourceExhausted;
+ break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead + 1))
+ {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead)
+ {
+ case 5: ch += *source++; ch <<= 6;
+ case 4: ch += *source++; ch <<= 6;
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd)
+ {
+ source -= extraBytesToRead + 1; /* Back up the source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ if (ch <= UNI_MAX_LEGAL_UTF32)
+ {
+ /*
+ * UTF-16 surrogate values are illegal in UTF-32, and anything
+ * over Plane 17 (> 0x10FFFF) is illegal.
+ */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
+ {
+ if (flags == strictConversion)
+ {
+ source -= extraBytesToRead + 1; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ else
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ else
+ *target++ = ch;
+ }
+ else /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
+ {
+ result = sourceIllegal;
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* ---------------------------------------------------------------------
+
+ Note A.
+ The fall-through switches in UTF-8 reading code save a
+ temp variable, some decrements & conditionals. The switches
+ are equivalent to the following loop:
+ {
+ int tmpBytesToRead = extraBytesToRead+1;
+ do {
+ ch += *source++;
+ --tmpBytesToRead;
+ if (tmpBytesToRead) ch <<= 6;
+ } while (tmpBytesToRead > 0);
+ }
+ In UTF-8 writing code, the switches on "bytesToWrite" are
+ similarly unrolled loops.
+
+ --------------------------------------------------------------------- */
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/ConvertUTF.h b/Frameworks/SSEQPlayer/SSEQPlayer/ConvertUTF.h
new file mode 100644
index 000000000..c363ffa1c
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/ConvertUTF.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* ---------------------------------------------------------------------
+
+ Conversions between UTF32, UTF-16, and UTF-8. Header file.
+
+ Several funtions are included here, forming a complete set of
+ conversions between the three formats. UTF-7 is not included
+ here, but is handled in a separate source file.
+
+ Each of these routines takes pointers to input buffers and output
+ buffers. The input buffers are const.
+
+ Each routine converts the text between *sourceStart and sourceEnd,
+ putting the result into the buffer between *targetStart and
+ targetEnd. Note: the end pointers are *after* the last item: e.g.
+ *(sourceEnd - 1) is the last item.
+
+ The return result indicates whether the conversion was successful,
+ and if not, whether the problem was in the source or target buffers.
+ (Only the first encountered problem is indicated.)
+
+ After the conversion, *sourceStart and *targetStart are both
+ updated to point to the end of last text successfully converted in
+ the respective buffers.
+
+ Input parameters:
+ sourceStart - pointer to a pointer to the source buffer.
+ The contents of this are modified on return so that
+ it points at the next thing to be converted.
+ targetStart - similarly, pointer to pointer to the target buffer.
+ sourceEnd, targetEnd - respectively pointers to the ends of the
+ two buffers, for overflow checking only.
+
+ These conversion functions take a ConversionFlags argument. When this
+ flag is set to strict, both irregular sequences and isolated surrogates
+ will cause an error. When the flag is set to lenient, both irregular
+ sequences and isolated surrogates are converted.
+
+ Whether the flag is strict or lenient, all illegal sequences will cause
+ an error return. This includes sequences such as: , ,
+ or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
+ must check for illegal sequences.
+
+ When the flag is set to lenient, characters over 0x10FFFF are converted
+ to the replacement character; otherwise (when the flag is set to strict)
+ they constitute an error.
+
+ Output parameters:
+ The value "sourceIllegal" is returned from some routines if the input
+ sequence is malformed. When "sourceIllegal" is returned, the source
+ value will point to the illegal value that caused the problem. E.g.,
+ in UTF-8 when a sequence is malformed, it points to the start of the
+ malformed sequence.
+
+ Author: Mark E. Davis, 1994.
+ Rev History: Rick McGowan, fixes & updates May 2001.
+ Fixes & updates, Sept 2001.
+
+------------------------------------------------------------------------ */
+
+#ifndef _CONVERTUTF_H_
+#define _CONVERTUTF_H_
+
+/* ---------------------------------------------------------------------
+ The following 4 definitions are compiler-specific.
+ The C standard does not guarantee that wchar_t has at least
+ 16 bits, so wchar_t is no less portable than unsigned short!
+ All should be unsigned values to avoid sign extension during
+ bit mask & shift operations.
+------------------------------------------------------------------------ */
+
+typedef unsigned long UTF32; /* at least 32 bits */
+typedef unsigned short UTF16; /* at least 16 bits */
+typedef unsigned char UTF8; /* typically 8 bits */
+
+/* Some fundamental constants */
+static const UTF32 UNI_REPLACEMENT_CHAR = 0x0000FFFD;
+static const UTF32 UNI_MAX_BMP = 0x0000FFFF;
+static const UTF32 UNI_MAX_UTF16 = 0x0010FFFF;
+static const UTF32 UNI_MAX_UTF32 = 0x7FFFFFFF;
+static const UTF32 UNI_MAX_LEGAL_UTF32 = 0x0010FFFF;
+
+enum ConversionResult
+{
+ conversionOK, /* conversion successful */
+ sourceExhausted, /* partial character in source, but hit end */
+ targetExhausted, /* insuff. room in target for conversion */
+ sourceIllegal /* source sequence is illegal/malformed */
+};
+
+enum ConversionFlags
+{
+ strictConversion,
+ lenientConversion
+};
+
+ConversionResult ConvertUTF8toUTF16(const UTF8 **, const UTF8 *, UTF16 **, UTF16 *, ConversionFlags);
+
+ConversionResult ConvertUTF16toUTF8(const UTF16 **, const UTF16 *, UTF8 **, UTF8 *, ConversionFlags);
+
+ConversionResult ConvertUTF8toUTF32(const UTF8 **, const UTF8 *, UTF32 **, UTF32 *, ConversionFlags);
+
+ConversionResult ConvertUTF32toUTF8(const UTF32 **, const UTF32 *, UTF8 **, UTF8 *, ConversionFlags);
+
+ConversionResult ConvertUTF16toUTF32(const UTF16 **, const UTF16 *, UTF32 **, UTF32 *, ConversionFlags);
+
+ConversionResult ConvertUTF32toUTF16(const UTF32 **, const UTF32 *, UTF16 **, UTF16 *, ConversionFlags);
+
+bool isLegalUTF8Sequence(const UTF8 *, const UTF8 *);
+
+/* --------------------------------------------------------------------- */
+
+#endif
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/FATSection.cpp b/Frameworks/SSEQPlayer/SSEQPlayer/FATSection.cpp
new file mode 100644
index 000000000..5062b60c2
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/FATSection.cpp
@@ -0,0 +1,40 @@
+/*
+ * SSEQ Player - SDAT FAT (File Allocation Table) Section structures
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ * Last modification on 2013-03-21
+ *
+ * Nintendo DS Nitro Composer (SDAT) Specification document found at
+ * http://www.feshrine.net/hacking/doc/nds-sdat.html
+ */
+
+#include
+#include "FATSection.h"
+
+FATRecord::FATRecord() : offset(0)
+{
+}
+
+void FATRecord::Read(PseudoFile &file)
+{
+ this->offset = file.ReadLE();
+ file.ReadLE(); // size
+ uint32_t reserved[2];
+ file.ReadLE(reserved);
+}
+
+FATSection::FATSection() : records()
+{
+}
+
+void FATSection::Read(PseudoFile &file)
+{
+ int8_t type[4];
+ file.ReadLE(type);
+ if (!VerifyHeader(type, "FAT "))
+ throw std::runtime_error("SDAT FAT Section invalid");
+ file.ReadLE(); // size
+ uint32_t count = file.ReadLE();
+ this->records.resize(count);
+ for (uint32_t i = 0; i < count; ++i)
+ this->records[i].Read(file);
+}
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/FATSection.h b/Frameworks/SSEQPlayer/SSEQPlayer/FATSection.h
new file mode 100644
index 000000000..198cfae12
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/FATSection.h
@@ -0,0 +1,33 @@
+/*
+ * SSEQ Player - SDAT FAT (File Allocation Table) Section structures
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ * Last modification on 2013-03-21
+ *
+ * Nintendo DS Nitro Composer (SDAT) Specification document found at
+ * http://www.feshrine.net/hacking/doc/nds-sdat.html
+ */
+
+#ifndef SSEQPLAYER_FATSECTION_H
+#define SSEQPLAYER_FATSECTION_H
+
+#include "common.h"
+
+struct FATRecord
+{
+ uint32_t offset;
+
+ FATRecord();
+
+ void Read(PseudoFile &file);
+};
+
+struct FATSection
+{
+ std::vector records;
+
+ FATSection();
+
+ void Read(PseudoFile &file);
+};
+
+#endif
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/INFOEntry.cpp b/Frameworks/SSEQPlayer/SSEQPlayer/INFOEntry.cpp
new file mode 100644
index 000000000..8bc69bdea
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/INFOEntry.cpp
@@ -0,0 +1,48 @@
+/*
+ * SSEQ Player - SDAT INFO Entry structures
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ * Last modification on 2013-03-21
+ *
+ * Nintendo DS Nitro Composer (SDAT) Specification document found at
+ * http://www.feshrine.net/hacking/doc/nds-sdat.html
+ */
+
+#include "INFOEntry.h"
+
+INFOEntrySEQ::INFOEntrySEQ() : fileID(0), bank(0), vol(0)
+{
+}
+
+void INFOEntrySEQ::Read(PseudoFile &file)
+{
+ this->fileID = file.ReadLE();
+ file.ReadLE(); // unknown
+ this->bank = file.ReadLE();
+ this->vol = file.ReadLE();
+ if (!this->vol)
+ this->vol = 0x7F; // Prevents nothing for volume
+ file.ReadLE(); // cpr
+ file.ReadLE(); // ppr
+ file.ReadLE(); // ply
+}
+
+INFOEntryBANK::INFOEntryBANK() : fileID(0)
+{
+ memset(this->waveArc, 0, sizeof(this->waveArc));
+}
+
+void INFOEntryBANK::Read(PseudoFile &file)
+{
+ this->fileID = file.ReadLE();
+ file.ReadLE(); // unknown
+ file.ReadLE(this->waveArc);
+}
+
+INFOEntryWAVEARC::INFOEntryWAVEARC() : fileID(0)
+{
+}
+
+void INFOEntryWAVEARC::Read(PseudoFile &file)
+{
+ this->fileID = file.ReadLE();
+}
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/INFOEntry.h b/Frameworks/SSEQPlayer/SSEQPlayer/INFOEntry.h
new file mode 100644
index 000000000..0a4b4dd7b
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/INFOEntry.h
@@ -0,0 +1,54 @@
+/*
+ * SSEQ Player - SDAT INFO Entry structures
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ * Last modification on 2013-03-21
+ *
+ * Nintendo DS Nitro Composer (SDAT) Specification document found at
+ * http://www.feshrine.net/hacking/doc/nds-sdat.html
+ */
+
+#ifndef SSEQPLAYER_INFOENTRY_H
+#define SSEQPLAYER_INFOENTRY_H
+
+#include "common.h"
+
+struct INFOEntry
+{
+ virtual ~INFOEntry()
+ {
+ }
+
+ virtual void Read(PseudoFile &file) = 0;
+};
+
+struct INFOEntrySEQ : INFOEntry
+{
+ uint16_t fileID;
+ uint16_t bank;
+ uint8_t vol;
+
+ INFOEntrySEQ();
+
+ void Read(PseudoFile &file);
+};
+
+struct INFOEntryBANK : INFOEntry
+{
+ uint16_t fileID;
+ uint16_t waveArc[4];
+
+ INFOEntryBANK();
+
+ void Read(PseudoFile &file);
+};
+
+struct INFOEntryWAVEARC : INFOEntry
+{
+ uint16_t fileID;
+
+ INFOEntryWAVEARC();
+
+ void Read(PseudoFile &file);
+};
+
+#endif
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/INFOSection.cpp b/Frameworks/SSEQPlayer/SSEQPlayer/INFOSection.cpp
new file mode 100644
index 000000000..c7bffc198
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/INFOSection.cpp
@@ -0,0 +1,60 @@
+/*
+ * SSEQ Player - SDAT INFO Section structures
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ * Last modification on 2013-03-25
+ *
+ * Nintendo DS Nitro Composer (SDAT) Specification document found at
+ * http://www.feshrine.net/hacking/doc/nds-sdat.html
+ */
+
+#include
+#include "INFOSection.h"
+
+template INFORecord::INFORecord() : entries()
+{
+}
+
+template void INFORecord::Read(PseudoFile &file, uint32_t startOffset)
+{
+ uint32_t count = file.ReadLE();
+ auto entryOffsets = std::vector(count);
+ file.ReadLE(entryOffsets);
+ for (uint32_t i = 0; i < count; ++i)
+ if (entryOffsets[i])
+ {
+ file.pos = startOffset + entryOffsets[i];
+ this->entries[i] = T();
+ this->entries[i].Read(file);
+ }
+}
+
+INFOSection::INFOSection() : SEQrecord(), BANKrecord(), WAVEARCrecord()
+{
+}
+
+void INFOSection::Read(PseudoFile &file)
+{
+ uint32_t startOfINFO = file.pos;
+ int8_t type[4];
+ file.ReadLE(type);
+ if (!VerifyHeader(type, "INFO"))
+ throw std::runtime_error("SDAT INFO Section invalid");
+ file.ReadLE(); // size
+ uint32_t recordOffsets[8];
+ file.ReadLE(recordOffsets);
+ if (recordOffsets[REC_SEQ])
+ {
+ file.pos = startOfINFO + recordOffsets[REC_SEQ];
+ this->SEQrecord.Read(file, startOfINFO);
+ }
+ if (recordOffsets[REC_BANK])
+ {
+ file.pos = startOfINFO + recordOffsets[REC_BANK];
+ this->BANKrecord.Read(file, startOfINFO);
+ }
+ if (recordOffsets[REC_WAVEARC])
+ {
+ file.pos = startOfINFO + recordOffsets[REC_WAVEARC];
+ this->WAVEARCrecord.Read(file, startOfINFO);
+ }
+}
diff --git a/Frameworks/SSEQPlayer/SSEQPlayer/INFOSection.h b/Frameworks/SSEQPlayer/SSEQPlayer/INFOSection.h
new file mode 100644
index 000000000..a41361a46
--- /dev/null
+++ b/Frameworks/SSEQPlayer/SSEQPlayer/INFOSection.h
@@ -0,0 +1,37 @@
+/*
+ * SSEQ Player - SDAT INFO Section structures
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ * Last modification on 2013-03-21
+ *
+ * Nintendo DS Nitro Composer (SDAT) Specification document found at
+ * http://www.feshrine.net/hacking/doc/nds-sdat.html
+ */
+
+#ifndef SSEQPLAYER_INFOSECTION_H
+#define SSEQPLAYER_INFOSECTION_H
+
+#include