From 7a9ea3a510f5fab31cebfe1c613af3512b62b768 Mon Sep 17 00:00:00 2001 From: Chris Heimlich Date: Sat, 20 Feb 2021 18:14:07 -0500 Subject: [PATCH] Fix for non-functional MP3 based SMFs - Discovered purpose of two uint32 values in SMF header: Roughly Major and Minor version. Major is always 1, minor is 0 for "proto" (likely during development) WAV based SMFs that seem unused in game, 2 is for in-use WAV based SMFs and 2 is for in-use MP3 based SMFs - Updated the creation/detection of WAV/MP3s and their SMF counterparts to make use of the above information, the lack of which was preventing MP3s from working entirely since a minor value of 1 was errantly being assigned to them --- src/smf.cpp | 35 ++++++++++++++++++++++------------- src/smf.h | 14 ++++++-------- src/version.h | 8 ++++---- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/smf.cpp b/src/smf.cpp index c918f7d..a3f3c9c 100644 --- a/src/smf.cpp +++ b/src/smf.cpp @@ -16,8 +16,22 @@ Smf::Smf(QByteArray rawData) : mFileDataF(rawData) } //-Class Functions--------------------------------------------------------------------------------------------------- -Smf Smf::fromStandard(Wav wavData) { return addSMFHeader(wavData.getFullData()); } -Smf Smf::fromStandard(Mp3 mp3Data) { return addSMFHeader(mp3Data.getFullData()); } +Smf Smf::fromStandard(Wav wavData) +{ + QByteArray sig = Qx::ByteArray::RAWFromString(SMF_SIG); + QByteArray maj = Qx::ByteArray::RAWFromPrimitive(MAJ_VER_STD); + QByteArray min = Qx::ByteArray::RAWFromPrimitive(MIN_VER_STD_WAV); + + return Smf(sig + maj + min + wavData.getFullData()); +} +Smf Smf::fromStandard(Mp3 mp3Data) +{ + QByteArray sig = Qx::ByteArray::RAWFromString(SMF_SIG); + QByteArray maj = Qx::ByteArray::RAWFromPrimitive(MAJ_VER_STD); + QByteArray min = Qx::ByteArray::RAWFromPrimitive(MIN_VER_STD_MP3); + + return Smf(sig + maj + min + mp3Data.getFullData()); +} //-Instance Functions------------------------------------------------------------------------------------------------ //Private: @@ -28,18 +42,18 @@ bool Smf::fileIsValidSMF() // General QByteArray smfSigRegion = headers.left(L_SMF_SIG); - QByteArray unkFlagOne = headers.mid(L_SMF_SIG, L_SMF_CMN_FLAGS/2); // Not understood so unused - QByteArray unkFlagTwo = headers.mid(L_SMF_SIG + L_SMF_CMN_FLAGS/2, L_SMF_CMN_FLAGS/2); // Not understood so unused + uint32_t majorVersion = Qx::ByteArray::RAWToPrimitive(headers.mid(L_SMF_SIG, L_SMF_MAJ_VER)); // So far haven't seen SMF with non-1 here so unused + uint32_t minorVersion = Qx::ByteArray::RAWToPrimitive(headers.mid(L_SMF_SIG + L_SMF_MAJ_VER, L_SMF_MIN_VER)); if(smfSigRegion == SMF_SIG) { // WAV Check - if(toWav().isValid()) + if((minorVersion == MIN_VER_STD_PROTO_WAV || minorVersion == MIN_VER_STD_WAV) && toWav().isValid()) { mType = WAVE; return true; } - else if(toMp3().isValid()) // MP3 Check + else if(minorVersion == MIN_VER_STD_MP3 && toMp3().isValid()) // MP3 Check { mType = MP3; return true; @@ -50,15 +64,10 @@ bool Smf::fileIsValidSMF() return false; } -QByteArray Smf::addSMFHeader(const QByteArray& fileData) -{ - return Qx::ByteArray::RAWFromString(Smf::SMF_SIG) + QByteArray(Smf::SMF_CMN_FLAGS, 8) + fileData; -} - //Public: bool Smf::isValid() { return !mFileDataF.isNull(); } Smf::Type Smf::getType() { return mType; } QByteArray Smf::getFullData() { return mFileDataF; } -Wav Smf::toWav() { return Wav(mFileDataF.mid(L_SMF_SIG + L_SMF_CMN_FLAGS)); } // Uses unknown flag values that seem to be common to a huge majority of SMFs -Mp3 Smf::toMp3() { return Mp3(mFileDataF.mid(L_SMF_SIG + L_SMF_CMN_FLAGS)); } // Uses unknown flag values that seem to be common to a huge majority of SMFs +Wav Smf::toWav() { return Wav(mFileDataF.mid(L_SMF_SIG + L_SMF_MAJ_VER + L_SMF_MIN_VER)); } +Mp3 Smf::toMp3() { return Mp3(mFileDataF.mid(L_SMF_SIG + L_SMF_MAJ_VER + L_SMF_MIN_VER)); } diff --git a/src/smf.h b/src/smf.h index 9260fbc..7c6e67d 100644 --- a/src/smf.h +++ b/src/smf.h @@ -17,13 +17,14 @@ class Smf static inline const QString FILE_EXT = "smf"; static inline const QString SMF_SIG = "fssm"; - - static inline const char SMF_CMN_FLAGS[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; //This appears to actually be two back-to-back, - // 32-bit, little-endian values of 1 that may be some kind of count. A few older looking BSCs use 1,0 instead, perhaps its a version tag? Initialized - // using char[] because QByteArray seems to be bugged when using "inline" with null (0x00) characters as part of the array + static inline const uint32_t MAJ_VER_STD = 1; + static inline const uint32_t MIN_VER_STD_PROTO_WAV = 0; // Seems to be in unused/really old SMFs, unused in this app for now + static inline const uint32_t MIN_VER_STD_WAV = 1; + static inline const uint32_t MIN_VER_STD_MP3 = 2; static const int L_SMF_SIG = 0x04; - static const int L_SMF_CMN_FLAGS = 0x08; + static const int L_SMF_MAJ_VER = 0x04; + static const int L_SMF_MIN_VER = 0x04; //-Instance Variables-------------------------------------------------------------------------------------------- private: @@ -36,9 +37,6 @@ class Smf Smf(QByteArray rawSMFData); //-Class Functions------------------------------------------------------------------------------------------------------- -private: - static QByteArray addSMFHeader(const QByteArray& fileData); - public: static Smf fromStandard(Wav wavData); static Smf fromStandard(Mp3 mp3Data); diff --git a/src/version.h b/src/version.h index 5d64071..4e72027 100644 --- a/src/version.h +++ b/src/version.h @@ -1,11 +1,11 @@ #ifndef VERSION_H #define VERSION_H -#define VER_FILEVERSION 0,1,7,0 -#define VER_FILEVERSION_STR "0.1.7.0" +#define VER_FILEVERSION 0,1,8,0 +#define VER_FILEVERSION_STR "0.1.8.0" -#define VER_PRODUCTVERSION 0,1,7,0 -#define VER_PRODUCTVERSION_STR "0.1.7.0" +#define VER_PRODUCTVERSION 0,1,8,0 +#define VER_PRODUCTVERSION_STR "0.1.8.0" #define VER_COMPANYNAME_STR "Obby Apps" #define VER_FILEDESCRIPTION_STR "BSCWorks (CoH:v14)"