Skip to content

Commit

Permalink
- Added warning notification for user if BSC version is different than
Browse files Browse the repository at this point in the history
14
- Simplified calls to SoundContainer::deinterpretData by making them
part of Playlist::deinterpretData, eliminating the need to call the
former independently
- Fixed a typo in the SoundContainer interpretation step that caused the
read value for "Is Looped" to errantly be used for "Using Speed Volume
Trigger" while opening a file
- Increased the decimal precision of all QDoubleSpinBoxs to prevent
rounding of all but extremely precise floating point values, in which
case the change to the rounded value would result in an all but
imperceptible change to sounds in-game
- Changed the conversion of QByteArray to QString used in the external
library Qx::String::fromByteArray to a method that circumvents QString's
constructor and cast operator
  validity checking, which ensures that terminating characters (0x00)
are ignored and no data is modified during the type conversion. This
caused some BSC EffectContainer data to be set to null after opening
  a file depending on its contents
- Added an additional use of mAlteringSoundContainerBoxEntries to
temporarily disable the effects of the VoiceGroup combo-box signals
while they are being loaded in order to prevent an unintended change in
the "File Saved" state of the editor
- Clarified the names of functions that interact with only the UI and
not the open BSC itself
- Added additional checks for mFileOpen in order to prevent crashes due
to null references when updating certain widget states after closing a
file, or before opening a file
  • Loading branch information
oblivioncth committed May 9, 2020
1 parent b26d96f commit c9ee010
Show file tree
Hide file tree
Showing 15 changed files with 188 additions and 132 deletions.
12 changes: 6 additions & 6 deletions CoH_BSC_Editor.pro
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ RESOURCES += \

RC_FILE = resources.rc

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lQx_static32_0-0-1-1_Qt_5-14-0
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lQx_static32_0-0-1-1_Qt_5-14-0d
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lQx_static32_0-0-1-2_Qt_5-14-0
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lQx_static32_0-0-1-2_Qt_5-14-0d

INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD/include

win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/lib/libQx_static32_0-0-1-1_Qt_5-14-0.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/lib/libQx_static32_0-0-1-1_Qt_5-14-0d.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/lib/Qx_static32_0-0-1-1_Qt_5-14-0.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/lib/Qx_static32_0-0-1-1_Qt_5-14-0d.lib
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/lib/libQx_static32_0-0-1-2_Qt_5-14-0.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/lib/libQx_static32_0-0-1-2_Qt_5-14-0d.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/lib/Qx_static32_0-0-1-2_Qt_5-14-0.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/lib/Qx_static32_0-0-1-2_Qt_5-14-0d.lib
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ There are still considerable unknowns regarding the BSC format that unfortunatel
- [ ] Add support for window resizing/fullscreen

## Source
This tool was written in C++ 17 along with Qt 5 and currently only targets Windows Vista and above; however, this tool can easily be ported to Linux with minimal changes, though to what end I am not sure since this is for a Windows game. The source includes an easy-to-use .pro file if you wish to build the application in Qt Creator and the available release was compiled in Qt Creator 4.10.0 using MSVC 2017 and a static compilation of Qt 5.12.3. Other than a C++ 17 capable compiler and Qt 5.12.x+ all files required to compile this software are included.
This tool was written in C++ 17 along with Qt 5 and currently only targets Windows Vista and above; however, this tool can easily be ported to Linux with minimal changes, though to what end I am not sure since this is for a Windows game. The source includes an easy-to-use .pro file if you wish to build the application in Qt Creator and the available latest release was compiled in Qt Creator 4.12.0 using MSVC 2019 and a static compilation of Qt 5.14.0. Other than a C++ 17 capable compiler and Qt 5.14.x+ all files required to compile this software are included, with the exception of a standard make file.

All functions/variables under the "Qx" (QExtended) namespace belong to a small, personal library I maintain to always have access to frequently used functionality in my projects. A pre-compiled static version of this library is provided with the source for this tool. If anyone truly needs it, I can provide the source for this library as well.

Expand Down
2 changes: 1 addition & 1 deletion include/qx.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ class String
static bool isValidMMRB(QString version);
static bool isHexNumber(QString hexNum);
static bool isValidChecksum(QString checksum, QCryptographicHash::Algorithm hashAlgorithm);
static QString fromByteArray(QByteArray data);
static QString fromByteArrayDirectly(QByteArray data);
static QString fromByteArrayHex(QByteArray data);
static QString fromByteArrayHex(QByteArray data, QChar separator, Endian::Endianness endianness);
static QString stripToHexOnly(QString string);
Expand Down
Binary file removed lib/Qx_static32_0-0-1-1_Qt_5-14-0.lib
Binary file not shown.
Binary file removed lib/Qx_static32_0-0-1-1_Qt_5-14-0d.lib
Binary file not shown.
Binary file removed lib/Qx_static32_0-0-1-1_Qt_5-14-0d.pdb
Binary file not shown.
Binary file added lib/Qx_static32_0-0-1-2_Qt_5-14-0.lib
Binary file not shown.
Binary file added lib/Qx_static32_0-0-1-2_Qt_5-14-0d.lib
Binary file not shown.
Binary file added lib/Qx_static32_0-0-1-2_Qt_5-14-0d.pdb
Binary file not shown.
37 changes: 20 additions & 17 deletions src/bsc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,20 @@ BSC::BSC()

// Segmented Interpreted Data
mTweenerI = "00 00 00 00 00";
mFormatVerI = FORMAT_TAG_DEFAULT;
mFormatVerI = FORMAT_VER_DEFAULT;
mPlaylistCountI = PLAYLIST_COUNT_DEFAULT;
}

//-Class Functions------------------------------------------------------------------------------------------------
//Public:
bool BSC::fileIsValidBSC(QFile& possibleBSC, Qx::IO::IOOpReport& reportBuffer)
bool BSC::fileIsValidBSC(QFile& possibleBSC, Qx::IO::IOOpReport& reportBuffer, bool& versionMismatch)
{
QByteArray headerSection;
reportBuffer = Qx::IO::readBytesFromFile(headerSection, possibleBSC, 0, 12);
reportBuffer = Qx::IO::readBytesFromFile(headerSection, possibleBSC, 0, 16);
versionMismatch = headerSection.mid(13, 4) != FORMAT_VER_TARGET_RAW;

return reportBuffer.wasSuccessful() &&
Qx::String::fromByteArray(headerSection.left(4)) == BSC::EA_SHARK_SIG && Qx::String::fromByteArray(headerSection.mid(9, 4)) == BSC::BSC_SIG;
Qx::String::fromByteArrayDirectly(headerSection.left(4)) == EA_SHARK_SIG && Qx::String::fromByteArrayDirectly(headerSection.mid(9, 4)) == BSC::BSC_SIG;
}

//-Instance Functions------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -77,24 +78,23 @@ QByteArray BSC::rebuildRawFile()
std::function<void(BSC::Playlist& parentPlaylist)> recursiveSubPlaylistDeinterpriation;
recursiveSubPlaylistDeinterpriation = [&recursiveSubPlaylistDeinterpriation](BSC::Playlist& parentPlaylist)->void
{
for(int i = 0; i <parentPlaylist.subPlaylistCount(); i++)
for(int i = 0; i < parentPlaylist.subPlaylistCount(); i++)
{
parentPlaylist.getSubPlaylistsR()[i].deinterpretData();
for(int j = 0; j <parentPlaylist.getSubPlaylistsR()[i].soundContainerCount(); j++)
parentPlaylist.getSubPlaylistsR()[i].getSoundContainersR()[j].deinterpretData();

recursiveSubPlaylistDeinterpriation(parentPlaylist.getSubPlaylistsR()[i]);
}
};

// Dump all interpreted data back to raw

// Top level data
deinterpretData();

// Playlist data
for(int i = 0; i < mPlaylists.length(); i++)
{
// Top level playlist
mPlaylists[i].deinterpretData();
for(int j = 0; j < mPlaylists[i].soundContainerCount(); j++)
mPlaylists[i].getSoundContainersR()[j].deinterpretData();

// Sub playlists
recursiveSubPlaylistDeinterpriation(mPlaylists[i]);
Expand Down Expand Up @@ -262,6 +262,9 @@ void BSC::Playlist::deinterpretData()

mOverrideParentBehaviorsR = Qx::ByteArray::RAWFromPrimitive(mOverrideParentBehaviorsI);
mEmitterR = enumEmitterToRaw(mEmitterI);

for(int i = 0; i < mSoundContainers.length(); i++)
mSoundContainers[i].deinterpretData();
}

QByteArray BSC::Playlist::getRestitchedData()
Expand Down Expand Up @@ -339,10 +342,10 @@ void BSC::Playlist::separateData(int &dataCursor, QByteArray &rawData)
uint32_t scNum;
uint32_t spNum;

// Data cursor starts on container index (or playback mode name) from parent BSC
// Data cursor starts on container index (or playback mode name length if not sub-playlist) from parent BSC
if(mSubPlaylist)
{
mPlaylistIndexR =rawData.mid(dataCursor,L_SUB_PL_INDEX);
mPlaylistIndexR = rawData.mid(dataCursor,L_SUB_PL_INDEX);
dataCursor += L_SUB_PL_INDEX; // Move to playback mode name length start
}

Expand All @@ -369,7 +372,7 @@ void BSC::Playlist::separateData(int &dataCursor, QByteArray &rawData)
mReleaseTimeR = rawData.mid(dataCursor,L_RELEASE_TIME);
dataCursor += L_RELEASE_TIME; // Move to number of effect behaviors
ebNum = qFromLittleEndian<quint32>(rawData.mid(dataCursor,L_EFF_BEH_NUM));
dataCursor += L_EFF_BEH_NUM; // Move to first effect behavior name length byte
dataCursor += L_EFF_BEH_NUM; // Move to first effect behavior name length byte\override flag if no effect behaviors

for(int i = 0; i < int(ebNum); i++)
{
Expand All @@ -386,7 +389,7 @@ void BSC::Playlist::separateData(int &dataCursor, QByteArray &rawData)
mEmitterR = rawData.mid(dataCursor,int(emitterNameLength));
dataCursor += emitterNameLength; // Move to number of sound containers start
scNum = qFromLittleEndian<quint32>(rawData.mid(dataCursor,L_SND_CNTR_NUM));
dataCursor += L_SND_CNTR_NUM; // Move to first sound container index start
dataCursor += L_SND_CNTR_NUM; // Move to first sound container index start/sub-playlist count if no containers

// Create SoundContainers in order to continue sequential movement of the data cursor
for(int i = 0; i < int(scNum); i++)
Expand Down Expand Up @@ -660,15 +663,15 @@ void BSC::SoundContainer::interpretData()
// mContainerIndexI = qFromLittleEndian<qint32>(mContainerIndexR); // Not needed, index can be infered from list index when writing

// Voice Group
QString wholeString = Qx::String::fromByteArray(mVoiceGroupR);
QString wholeString = Qx::String::fromByteArrayDirectly(mVoiceGroupR);
int sepPos = wholeString.indexOf(VOICE_GROU_SEP);
mVoiceGroupFrontI = wholeString.left(sepPos);
mVoiceGroupBackI = wholeString.mid(sepPos + VOICE_GROU_SEP.length());

// Others
mIs3DI = Qx::ByteArray::RAWToPrimitive<bool>(mIs3DR);
mIsLoopedI = Qx::ByteArray::RAWToPrimitive<bool>(mIsLoopedR);
mUsingSpeedVolumeTriggerI = Qx::ByteArray::RAWToPrimitive<bool>(mIsLoopedR);
mUsingSpeedVolumeTriggerI = Qx::ByteArray::RAWToPrimitive<bool>(mUsingSpeedVolumeTriggerR);
mRandomWeightI = qFromLittleEndian<quint32>(mRandomWeightR);
mAmplitudeFactorI = Qx::ByteArray::RAWToPrimitive<float>(mAmplitudeFactorR, Qx::Endian::LE);
mDopplerRatioI = Qx::ByteArray::RAWToPrimitive<float>(mDopplerRatioR, Qx::Endian::LE);
Expand All @@ -681,7 +684,7 @@ void BSC::SoundContainer::interpretData()
mLinkedFilesI.append(mLinkedFilesR.value(i));

mEffectContainerCountI = qFromLittleEndian<quint32>(mEffectContainerCountR);
mEffectContainerDataI = Qx::String::fromByteArray(mEffectContainerDataR);
mEffectContainerDataI = Qx::String::fromByteArrayDirectly(mEffectContainerDataR);
}

BSC::SoundContainer::ReasonableSCType BSC::SoundContainer::determineReasonableSCDataType(QByteArray rawVal)
Expand Down
5 changes: 3 additions & 2 deletions src/bsc.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class BSC

static inline const QString TWEENER_DEFAULT = "00" + QString(TWEENER_BYTE_SEP) + "00" + QString(TWEENER_BYTE_SEP) + "00"
+ QString(TWEENER_BYTE_SEP) + "00" + QString(TWEENER_BYTE_SEP) + "00";
static const uint32_t FORMAT_TAG_DEFAULT = 14;
static inline const QByteArray FORMAT_VER_TARGET_RAW = Qx::ByteArray::RAWFromStringHex("0e000000");
static const uint32_t FORMAT_VER_DEFAULT = 14;
static const uint8_t PLAYLIST_COUNT_DEFAULT = 0;

static const int L_FORMAT_TAG_1 = 0x04; // easb
Expand Down Expand Up @@ -59,7 +60,7 @@ class BSC

//-Class Functions------------------------------------------------------------------------------------------------------
public:
static bool fileIsValidBSC(QFile& possibleBSC, Qx::IO::IOOpReport& reportBuffer);
static bool fileIsValidBSC(QFile& possibleBSC, Qx::IO::IOOpReport& reportBuffer, bool& versionMismatch);

private:

Expand Down
Loading

0 comments on commit c9ee010

Please sign in to comment.