Skip to content

Commit

Permalink
Merge pull request #2 from agfor/master
Browse files Browse the repository at this point in the history
Feature addition and bugfix to SCI resource compression tool. The audio resources of KQ5 CD and Jones CD can now be compressed.
  • Loading branch information
bluegr committed Aug 24, 2011
2 parents 60cfdba + ae181e0 commit e4650fa
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 38 deletions.
109 changes: 72 additions & 37 deletions engines/sci/compress_sci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,33 @@ CompressSci::CompressSci(const std::string &name) : CompressionTool(name, TOOLTY

_outputToDirectory = false;

_shorthelp = "Used to compress Sierra resource.aud/resource.sfx files. (NOT SCI32 compatible!)";
_shorthelp = "Used to compress Sierra resource.aud/.sfx and AUDIO001.002 files. (NOT SCI32 compatible!)";
_helptext = "\nUsage: " + getName() + " [mode-params] [-o outputname] <inputname>\n";
}

// header is first 6 bytes read from file
SciResourceDataType CompressSci::detectData(byte *header, bool compressMode) {
byte buffer[20];
uint32 dataSize;
if (_rawAudio) {
// File is a raw audio file
dataSize = _rawAudioMap[_inputOffset];
_inputEndOffset = _inputOffset + dataSize;
return kSciResourceDataTypeRaw;
}
byte buffer[20];
memcpy(&buffer, header, 6);
if ((memcmp(buffer + 1, "RIFF", 4) == 0) || (memcmp(buffer + 1, "\x8d\x0bSOL", 4) == 0)) {
// Fixup for pharkas resource.sfx, several WAVE files contain a size thats not right (-1 byte)
for (int i = 0; i < 5; i++)
// Fixup for pharkas resource.sfx, several WAVE files contain a size thats not right (-1 byte)
int offset = 0;
if (memcmp(buffer + 1, "RIFF", 4) == 0) {
offset = 5;
} else if ((memcmp(buffer + 1, "\x8d\x0bSOL\x00", 6) == 0) ||
(memcmp(buffer + 1, "\x8d\x0cSOL\x00", 6) == 0)) {
offset = 7;
}
if (offset) {
for (int i = 0; i < offset; i++)
buffer[i] = buffer[i + 1];
_input.read_throwsOnError(&buffer[5], 1);
_input.read_throwsOnError(&buffer[offset], 1);
_inputOffset++;
warning("WAVE resource position adjusted at %lx\n", _inputOffset);
}
Expand All @@ -97,9 +110,9 @@ SciResourceDataType CompressSci::detectData(byte *header, bool compressMode) {
_input.read_throwsOnError(&buffer[6], 8);
dataSize = READ_LE_UINT32(buffer + 9);
// HACK: LSL6 resource.aud has a SOL that specifies incorrect dataSize, we fix it here
if ((_inputOffset == 0x619bf07) && (dataSize == 0x1dd78))
if ((_inputOffset == 102350599) && (dataSize == 122232))
dataSize--;
if ((_inputOffset == 0x101DFBC5) && (dataSize == 0x1cfc1))
if ((_inputOffset == 270400453) && (dataSize == 118721))
dataSize--;
_inputEndOffset = _inputOffset + 14 + dataSize;
return kSciResourceDataTypeSOL;
Expand Down Expand Up @@ -220,7 +233,6 @@ static void deDPCM8(byte *soundBuf, byte *inputBuf, uint32 n) {
void CompressSci::compressData(SciResourceDataType dataType) {
int orgDataSize = _inputEndOffset - _inputOffset;
int newDataSize = 0;
byte *orgData = new byte[orgDataSize];
byte *newData = 0;

int sampleRate = 0;
Expand All @@ -230,18 +242,13 @@ void CompressSci::compressData(SciResourceDataType dataType) {
uint8 sampleBits = 8;
byte sampleFlags = 0;

if (!orgData)
error("malloc error");

switch (dataType) {
case kSciResourceDataTypeWAVE:
print("WAVE found\n");
if (!Audio::loadWAVFromStream(_input, sampleDataSize, sampleRate, sampleFlags))
error("Unable to read WAV at offset %lx", _inputOffset);

sampleData = new byte[sampleDataSize];
if (!sampleData)
error("malloc error");
_input.read_throwsOnError(sampleData, sampleDataSize);
if (sampleFlags & Audio::Mixer::FLAG_16BITS)
sampleBits = 16;
Expand All @@ -259,8 +266,6 @@ void CompressSci::compressData(SciResourceDataType dataType) {
_input.readByte();
// Now we read SOL datastream
sampleData = new byte[sampleDataSize];
if (!sampleData)
error("malloc error");
_input.read_throwsOnError(sampleData, sampleDataSize);

bool dataUnsigned = false;
Expand All @@ -281,12 +286,19 @@ void CompressSci::compressData(SciResourceDataType dataType) {
}
break;
}
case kSciResourceDataTypeRaw:
sampleRate = 11025;
// No headers so just use the original data as sample data
sampleDataSize = orgDataSize;
sampleData = new byte[sampleDataSize];
_input.read_throwsOnError(sampleData, sampleDataSize);
break;
case kSciResourceTypeTypeSync:
print("SYNC found at %lx\n", _inputOffset);
// Simply copy original data over
_input.read_throwsOnError(orgData, orgDataSize);
newData = orgData;
newDataSize = orgDataSize;
newData = new byte[newDataSize];
_input.read_throwsOnError(newData, newDataSize);
break;
default:
error("Unsupported datatype");
Expand All @@ -310,10 +322,26 @@ void CompressSci::compressData(SciResourceDataType dataType) {
}

_output.write(newData, newDataSize);
delete[] newData;
}

if ((newData) && (newData != orgData))
delete[] newData;
delete[] orgData;
uint CompressSci::parseRawAudioMap() {
Common::Filename mapFileName = _inputPaths[0].path;
// Assume the map is in the same dir as the resource file
// and is called AUDIO001.MAP
mapFileName.setFullName("AUDIO001.MAP");
print("Trying %s as resource map\n", mapFileName.getFullPath().data());
Common::File mapFile;
mapFile.open(mapFileName, "rb");
uint32 offset = 0;
// Ten byte entries, the last is fake, stop when it's reached
while (mapFile.readUint16LE() != 0xffff) {
// mask out the resource volume number
offset = mapFile.readUint32LE() & 0x0fffffff;
_rawAudioMap[offset] = mapFile.readUint32LE();
}
mapFile.close();
return _rawAudioMap.size();
}

void CompressSci::execute() {
Expand All @@ -323,12 +351,9 @@ void CompressSci::execute() {

_input.open(infile, "rb");
_inputSize = _input.size();
_rawAudio = false;

// First find out how many samples are in this file
// We only support SOL audio and WAVE
// We can't support games that use "raw" audio (would have to walk through audio map for those, which would
// complicate this code - all talkie games that use this (kq5) don't use much space anyway, so not supporting
// those isn't a big issue

_input.seek(0, SEEK_SET);
byte header[6];
Expand All @@ -343,19 +368,25 @@ void CompressSci::execute() {
error("This resource file is already FLAC-compressed, aborting...\n");

int resourceCount = 0;
do {
recognizedDataType = detectData(header, false);
if (!recognizedDataType)
error("Unsupported data at offset %lx", _inputOffset);
_input.seek(_inputEndOffset, SEEK_SET);
_inputOffset = _inputEndOffset;
resourceCount++;
// We abort even, if file position is one below size because of pharkas resource.sfx
if (_inputOffset >= _inputSize - 1)
break;
if (_input.size() == 97103872 || _input.size() == 23126016) {
print("Size matches KQ5 or Jones in the Fast Lane audio file, assuming raw audio\n");
_rawAudio = true;
resourceCount = parseRawAudioMap();
} else {
do {
recognizedDataType = detectData(header, false);
if (!recognizedDataType)
error("Unsupported data at offset %lx", _inputOffset);
_input.seek(_inputEndOffset, SEEK_SET);
_inputOffset = _inputEndOffset;
resourceCount++;
// We abort even, if file position is one below size because of pharkas resource.sfx
if (_inputOffset >= _inputSize - 1)
break;

_input.read_throwsOnError(&header, 6);
} while (true);
_input.read_throwsOnError(&header, 6);
} while (true);
}

// This case happens on pharkas resource.sfx
if (_inputOffset != _inputSize)
Expand Down Expand Up @@ -394,6 +425,10 @@ void CompressSci::execute() {
_input.seek(_inputOffset, SEEK_SET);
compressData(recognizedDataType);

// raw files are 0-padded to 2048 bytes
if (_rawAudio)
_inputEndOffset = (((_inputEndOffset - 1) >> 11) + 1) << 11;

// Seek inputfile to the end of the data
_input.seek(_inputEndOffset, SEEK_SET);
// Seek outputfile to mapping table
Expand Down
7 changes: 6 additions & 1 deletion engines/sci/compress_sci.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@
#define COMPRESS_SCI_H

#include "compress.h"
#include <map>

enum SciResourceDataType {
kSciResourceDataTypeUnknown = 0,
kSciResourceDataTypeWAVE = 1,
kSciResourceDataTypeSOL = 2,
kSciResourceTypeTypeSync = 3
kSciResourceTypeTypeSync = 3,
kSciResourceDataTypeRaw = 4
};

class CompressSci : public CompressionTool {
Expand All @@ -41,12 +43,15 @@ class CompressSci : public CompressionTool {
protected:
SciResourceDataType detectData(byte *header, bool compressMode);
void compressData(SciResourceDataType dataType);
uint parseRawAudioMap();

Common::File _input, _output;
int _inputOffset;
int _inputEndOffset;
int _inputSize;
int _outputOffset;
bool _rawAudio;
std::map<uint32,uint32> _rawAudioMap;
};

#endif

0 comments on commit e4650fa

Please sign in to comment.