This is a sound mod tutorial for PC version of Bully video game
-------------------------------
LONG STORY SHORT
-------------------------------
- download
PC sound kit.zip PC sound kit_v2.zip and extract it - Drag and Drop .bin file (from \AUDIO\PLAYLIST\) or .sea file (from \AUDIO\xact\) on export wav.bat
- Edit wavs you want and delete unmodified wavs
Modded audio must be same duration or shorter, same sample rate and channels as originals
- Save as wav s16 pcm. Don't change names
- Drag and Drop .bin or .sea file on import.bat
- Done!
FOR THOSE WHO WANT TO DIVE DEEPER
------------------------------------
GENERAL INFORMATION
------------------------------------
audio\PLAYLIST\ folder contains some .bin files:
Sound for cutscenes and dialogs resides in
Cuts.bin and
Speech.bin files
Music is in
Music.binAmbient sound, like birds, crowd noise, dogs, music class intro, preacher prayers etc are in
Ambs.binAside there is a
.LST files with same name as .bins (Cuts.lst Music.lst etc)
Its a
name list files.
You can open them with notepad if you need to
PC version:
.bin sound file or .sea file is archive containing
Sound Banks (.xsb idstring SDBK) and
Wave Banks (.xwb idstring WBND)
This banks is
microsoft's audio lib file types
We need
Wave Banks cos they are containing
raw wave dataCompressed as
Microsoft ADPCMFor all chimichanga we will need some tools:
------------------------------------------------------
2.EXTRACT SOUND FOR MODDING
------------------------------------------------------
to extract PC wave data in usable format, we can use
2wav.bms// Bully Scholarship Edition PC wav extrctor
// Extract wav file or files from .bin/.sea using this script
// use quickbms 2wav.bms <<Dir>>.bin or quickbms 2wav.bms <<Dir>>.sea to extract wav files
// Edit wav. Keep same duration or shorter. Save as wav s16 pcm (Speech - mono, Cuts - stereo)
get DirName basename
for
findloc Offset binary "WBND"
set BankOFFSET long OFFSET
math Offset + 0x2c
goto Offset
get DataOFFSET long
get DataSIZE long
get Unk1 long //flags?
get WavesCount long
getDString BankName 64
getDString Dummy 24
for i = 0 < WavesCount
get Dummy long
get AudioFormat long // binary32: BitsPerSample(1) BlockAlign(8) SampleRate(18) Channels(3) FormatTag(2)
// 0001 1000 0000 1010 1100 0100 0110 1010
// ||>>>>>>>> |>>>>>>>>>>>>>>>>>>>>>|>>>|format
// B|Align |SampleRate |channels
// format: 0-PCM; 1-XMA; 2-ADPCM; 3-WMA
//xmath Format "AudioFormat & 3" // 11 mask (2)
xmath numChannels[i] "AudioFormat >> 2 & 7" // 111 mask (3)
xmath SampleRate[i] "AudioFormat >> 5 & 262143" // 11 1111 1111 1111 1111 mask (18)
//xmath blockAlign "AudioFormat >> 23 & 255" // 1111 1111 mask (8)
xmath BitsPerSample[i] "AudioFormat >> 31 & 1" // 1 mask (1)
xmath BitsPerSample[i] "8 * BitsPerSample[i] + 8" // BitsPerSample(PCM only): 0-8bit; 1-16bit
get WaveOffset[i] long
get WaveSize[i] long
get Dummy long
get Dummy long
next i
for i = 0 < WavesCount
getDString WaveName[i] 64
next i
for i = 0 < WavesCount
xmath Offset "BankOFFSET + DataOFFSET + WaveOffset[i]"
callfunction WavHeader
next i
next
startfunction WavHeader
log MEMORY_FILE1 0 0
log MEMORY_FILE2 0 0
//create wav header in memory
set MEMORY_FILE2 binary "\x52\x49\x46\x46\x72\x21\x1E\x00\x57\x41\x56\x45\x66\x6D\x74\x20\x32\x00\x00\x00\x02\x00\x02\x00\x22\x56\x00\x00\x10\x5E\x00\x00\x8C\x00\x04\x00\x20\x00\x80\x00\x07\x00\x00\x01\x00\x00\x00\x02\x00\xFF\x00\x00\x00\x00\xC0\x00\x40\x00\xF0\x00\x00\x00\xCC\x01\x30\xFF\x88\x01\x18\xFF\x64\x61\x74\x61\x20\x21\x1E\x00"
//audio settings
if numChannels[i] = 2
set blockAlign short 140 //blockAlign 70(mono) or 140(stereo)
else
set blockAlign short 70
endif
//write settings to header
xmath SIZE "WaveSize[i] + 0x46"
putvarchr MEMORY_FILE2 0x04 SIZE long
putvarchr MEMORY_FILE2 0x16 numChannels[i] short // mono-stereo
putvarchr MEMORY_FILE2 0x18 SampleRate[i] long
xmath BYTERATE "(SampleRate[i] * BitsPerSample[i] * numChannels[i]) / 8"
putvarchr MEMORY_FILE2 0x1c BYTERATE long // (Sample Rate * BitsPerSample * Channels)/8
putvarchr MEMORY_FILE2 0x20 blockAlign short
putvarchr MEMORY_FILE2 0x4a WaveSize[i] long
//append audio data
log MEMORY_FILE1 Offset WaveSize[i]
append
log MEMORY_FILE2 0 WaveSize[i] MEMORY_FILE1
append
//write to wav file
get MF2Size asize MEMORY_FILE2
if WavesCount > 1 //SEA
string Name p "%s/%s_%s.wav" BankName i WaveName[i]
else //bin
string Name p "%s/%s.wav" DirName WaveName[i]
endif
log Name 0 MF2Size MEMORY_FILE2
endfunction
As a result, we will get folder named as bin or sea name with
wav files (MS ADPCM) in it
PC MSADPCM .wavs are
ready to edit with any audio editor you like(i.e.
audiacity)
Modded audio must be
same duration or shorter same
sample rate and
channels as original
Save as wav s16 pcm
----------------------------------------
5.COMPRESS SOUND BACK
----------------------------------------
for PC we can use cli tool
AdpcmEncode.exe from
Microsoft DirectX SDKAfter installation it will be in \Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x86\
encode example:
AdpcmEncode.exe Speech\Algie_CHATTER_v2.wav import\Algie_CHATTER_v2.wav
Speech\Algie_CHATTER_v2.wav is s16 pcm wav
import\Algie_CHATTER_v2.wav is output file with MS ADPCM 128 samples/block compression
Don't forget to remove unmoded(MSADPCM) wavs from Speech (or whatever your .bin/.sea name is) folder
otherwise AdpcmEncode will decode them
As a result we got our moded wavs MSADPCM encoded in import\ folder
Now, we need to cut out a RIFF header with
wav2dat.bms// MSADPCM wav header cutter quickbms script
idstring "RIFF"
goto 0x14
get FORMAT short
if FORMAT != 2
print "not a Microsoft ADPCM"
print "REMOVE ALL UNMODIFIED WAVS BEFORE IMPORT. IMPORTED WAVS MUST BE S16 PCM"
exit
endif
get FNAME BASENAME
string FName P "import/%FName%.dat"
Findloc DataOFFSET string "data"
goto DataOFFSET
get data long
get DataSIZE long
SavePos DataOFFSET
math DataSIZE - 0x80 //cut tail just in case
log FNAME DataOFFSET DataSIZE
sound dat is
ready to be imported in .bin/.sea------------------------------------------------------
5.IMPORTING MODDED SOUND BACK
------------------------------------------------------
Use
2dat.bms script with r and w options
quickbms -r -w 2dat.bms Cuts.bin
// Bully Scholarship Edition PC audio dat extrctor (wav without header)
// Extract dat file or files from .bin/.sea using this script
// use quickbms 2dat.bms <<Dir>>.bin or quickbms 2dat.bms <<Dir>>.sea to extract dat files
// use quickbms -r -w 2dat.bms <<Dir>>.bin or quickbms -r -w 2dat.bms <<Dir>>.sea
//to import dat files from "import" folder back to .bin/.sea
for
findloc Offset binary "WBND"
set BankOFFSET long OFFSET
math Offset + 0x2c
goto Offset
get DataOFFSET long
get DataSIZE long
get Unk1 long //flags?
get WavesCount long
getDString DirName 64
getDString Dummy 24
for i = 0 < WavesCount
get Dummy long
get AudioFormat long
get WaveOffset[i] long
get WaveSize[i] long
get Dummy long
get Dummy long
next i
for i = 0 < WavesCount
getDString WaveName[i] 64
next i
for i = 0 < WavesCount
xmath Offset "BankOFFSET + DataOFFSET + WaveOffset[i]"
if WavesCount > 1
string Name p "import/%s_%s.dat" i WaveName[i]
else
string Name p "import/%s.dat" WaveName[i]
endif
log Name Offset WaveSize[i]
next i
next
to import back sound dat file(s) from import folder to .bin/.sea (Cuts.bin in example above)
Now you can test modded .bin/.sea in game!
UPD: tutorial updated - add .SEA files support