Skip to content

Instantly share code, notes, and snippets.

@withmorten
Last active February 18, 2017 03:01
Show Gist options
  • Save withmorten/e6238bdc7ff7ddb695227dda7b7b1acc to your computer and use it in GitHub Desktop.
Save withmorten/e6238bdc7ff7ddb695227dda7b7b1acc to your computer and use it in GitHub Desktop.
cod5ff extract
<?php
const WAV_NEEDLE = "RIFF";
const WAVE = "WAVE";
const XWMA = "XWMA";
const FMT = "fmt ";
const DEFAULTPATH = "sound";
$ffdump = file_get_contents($argv[1]);
$lastpos = 0;
$lastpath = "";
$wav_pathid = hex2bin("FFFFFFFFFFFFFFFF");
$wav_strangepathid = hex2bin("FFFFFFFF");
$wav_strangeid = hex2bin("00000000FFFFFFFF");
$wavs = array();
$c = 0;
while(($lastpos = strpos($ffdump, WAV_NEEDLE, $lastpos)) !== FALSE) {
$wav_format = substr($ffdump, $lastpos+8, 4);
$fmt = $wav_format.substr($ffdump, $lastpos+12, 4);
if($fmt == WAVE.FMT || $fmt == XWMA.FMT) {
$block_start = strrpos($ffdump, $wav_pathid, -(strlen($ffdump) - ($lastpos -1)));
if($wav_pathid == substr($ffdump, $block_start, 8)) {
if($wav_strangeid == substr($ffdump, $lastpos-12, 8)) {
if(substr($ffdump, $block_start-4, 12) == ($wav_strangepathid.$wav_pathid)) {
$path_end = strpos($ffdump, hex2bin("00"), $block_start);
$lastpath = str_replace("\\", "/", substr($ffdump, $block_start+8, $path_end - ($block_start+8)));
$wav_name = $lastpath."/".substr($ffdump, $path_end+1, ($lastpos-13) - ($path_end+1));
} else {
$wav_name = $lastpath."/".substr($ffdump, $block_start+8, ($lastpos-13) - ($block_start+8));
}
$wav_length = substr($ffdump, $lastpos-4, 4);
} else {
$lastpath = "";
$wav_name = substr($ffdump, $block_start+12, ($lastpos - $block_start) - 13);
$wav_length = substr($ffdump, $block_start+8, 4);
}
$wav_name = str_replace("//", "/", $wav_name);
$wav_length = hexdec(bin2hex(strrev($wav_length)));;
$wavs[$c] = array("name" => $wav_name, "start" => $lastpos, "length" => $wav_length, "format" => $wav_format);
}
}
$c++;
$lastpos = $lastpos + strlen(WAV_NEEDLE);
}
if(!file_exists(DEFAULTPATH)) {
mkdir(DEFAULTPATH);
}
foreach($wavs as $c => $wav) {
$explodepath = explode("/", $wav["name"]);
$pathsize = count($explodepath);
$oldpath = DEFAULTPATH."/";
for($i = 1; $i <= $pathsize; $i++) {
$fullpath = $oldpath.$explodepath[$i-1];
if($i != $pathsize) {
if(!file_exists($fullpath)) {
mkdir($fullpath);
}
$oldpath = $fullpath."/";
} else {
file_put_contents($fullpath, substr($ffdump, $wav["start"], $wav["length"]));
$pcmpath = substr($fullpath, 0, -4)."_PCM.wav";
if($wav["format"] == WAVE) {
$cmd = "ffmpeg -y -i $fullpath -c:a pcm_s16le $pcmpath\n";
} else if($wav["format"] == XWMA) {
$cmd = "xwmaencode $fullpath $pcmpath\n";
}
echo $cmd;
}
}
}
?>
@withmorten
Copy link
Author

withmorten commented Jul 17, 2016

Works for the most part. Some files from mak.ff and see1.ff get not put into the correct path, they belong into voiceovers\makin\mast and voiceovers\see1\mast respectively. Use the same way as the cod4 script.

Note that many files are in better quality in the iwd files or the mod tools (ADPCM in iwd and source lossless WAV in mod tools). One file is a different file in the iwds and the ffs, namely "voiceovers/vfx/speech/speech_01.wav".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment