diff --git a/engines/sci/compress_sci.cpp b/engines/sci/compress_sci.cpp
index 3d82b7e..ec30bb6 100644
|
a
|
b
|
CompressSci::CompressSci(const std::string &name) : CompressionTool(name, TOOLTY
|
| 58 | 58 | |
| 59 | 59 | _outputToDirectory = false; |
| 60 | 60 | |
| 61 | | _shorthelp = "Used to compress Sierra resource.aud/resource.sfx files. (NOT SCI32 compatible!)"; |
| | 61 | _shorthelp = "Used to compress Sierra resource.aud/.sfx and AUDIO001.002 files. (NOT SCI32 compatible!)"; |
| 62 | 62 | _helptext = "\nUsage: " + getName() + " [mode-params] [-o outputname] <inputname>\n"; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | 65 | // header is first 6 bytes read from file |
| 66 | 66 | SciResourceDataType CompressSci::detectData(byte *header, bool compressMode) { |
| 67 | | byte buffer[20]; |
| 68 | 67 | uint32 dataSize; |
| | 68 | if (_rawAudio) { |
| | 69 | // File is a raw audio file |
| | 70 | dataSize = _rawAudioMap[_inputOffset]; |
| | 71 | _inputEndOffset = _inputOffset + dataSize; |
| | 72 | return kSciResourceDataTypeRaw; |
| | 73 | } |
| | 74 | byte buffer[20]; |
| 69 | 75 | memcpy(&buffer, header, 6); |
| 70 | 76 | if ((memcmp(buffer + 1, "RIFF", 4) == 0) || (memcmp(buffer + 1, "\x8d\x0bSOL", 4) == 0)) { |
| 71 | 77 | // Fixup for pharkas resource.sfx, several WAVE files contain a size thats not right (-1 byte) |
| … |
… |
static void deDPCM8(byte *soundBuf, byte *inputBuf, uint32 n) {
|
| 220 | 226 | void CompressSci::compressData(SciResourceDataType dataType) { |
| 221 | 227 | int orgDataSize = _inputEndOffset - _inputOffset; |
| 222 | 228 | int newDataSize = 0; |
| 223 | | byte *orgData = new byte[orgDataSize]; |
| 224 | 229 | byte *newData = 0; |
| 225 | 230 | |
| 226 | 231 | int sampleRate = 0; |
| … |
… |
void CompressSci::compressData(SciResourceDataType dataType) {
|
| 230 | 235 | uint8 sampleBits = 8; |
| 231 | 236 | byte sampleFlags = 0; |
| 232 | 237 | |
| 233 | | if (!orgData) |
| 234 | | error("malloc error"); |
| 235 | | |
| 236 | 238 | switch (dataType) { |
| 237 | 239 | case kSciResourceDataTypeWAVE: |
| 238 | 240 | print("WAVE found\n"); |
| … |
… |
void CompressSci::compressData(SciResourceDataType dataType) {
|
| 281 | 283 | } |
| 282 | 284 | break; |
| 283 | 285 | } |
| | 286 | case kSciResourceDataTypeRaw: |
| | 287 | sampleRate = 11025; |
| | 288 | // No headers so just use the original data as sample data |
| | 289 | sampleDataSize = orgDataSize; |
| | 290 | sampleData = new byte[sampleDataSize]; |
| | 291 | if (!sampleData) |
| | 292 | error("malloc error"); |
| | 293 | _input.read_throwsOnError(sampleData, sampleDataSize); |
| | 294 | break; |
| 284 | 295 | case kSciResourceTypeTypeSync: |
| 285 | 296 | print("SYNC found at %lx\n", _inputOffset); |
| 286 | 297 | // Simply copy original data over |
| 287 | | _input.read_throwsOnError(orgData, orgDataSize); |
| 288 | | newData = orgData; |
| 289 | 298 | newDataSize = orgDataSize; |
| | 299 | newData = new byte[newDataSize]; |
| | 300 | if (!newData) |
| | 301 | error("malloc error"); |
| | 302 | _input.read_throwsOnError(newData, newDataSize); |
| 290 | 303 | break; |
| 291 | 304 | default: |
| 292 | 305 | error("Unsupported datatype"); |
| … |
… |
void CompressSci::compressData(SciResourceDataType dataType) {
|
| 305 | 318 | Common::File tempfileEnc(TEMP_ENC, "rb"); |
| 306 | 319 | newDataSize = tempfileEnc.size(); |
| 307 | 320 | newData = new byte[newDataSize]; |
| | 321 | if (!newData) |
| | 322 | error("malloc error"); |
| 308 | 323 | tempfileEnc.read_throwsOnError(newData, newDataSize); |
| 309 | 324 | tempfileEnc.close(); |
| 310 | 325 | } |
| 311 | 326 | |
| 312 | 327 | _output.write(newData, newDataSize); |
| | 328 | delete[] newData; |
| | 329 | } |
| 313 | 330 | |
| 314 | | if ((newData) && (newData != orgData)) |
| 315 | | delete[] newData; |
| 316 | | delete[] orgData; |
| | 331 | uint CompressSci::parseRawAudioMap() { |
| | 332 | Common::Filename mapFileName = _inputPaths[0].path; |
| | 333 | // Assume the map is in the same dir as the resource file |
| | 334 | // and is called AUDIO001.MAP |
| | 335 | mapFileName.setFullName("AUDIO001.MAP"); |
| | 336 | warning("Trying %s as resource map\n", mapFileName.getFullPath().data()); |
| | 337 | Common::File mapFile; |
| | 338 | mapFile.open(mapFileName, "rb"); |
| | 339 | // Ten byte entries, the last one is fake |
| | 340 | uint32 numEntries = (mapFile.size() / 10) - 1; |
| | 341 | uint32 offset = 0; |
| | 342 | uint32 size = 0; |
| | 343 | for (uint32 i = 0; i < numEntries; i++) { |
| | 344 | // shouldn't reach the fake entry but break if we do |
| | 345 | if (mapFile.readUint16LE() == 0xffff) break; |
| | 346 | // mask out the resource volume number |
| | 347 | offset = mapFile.readUint32LE() & 0x0fffffff; |
| | 348 | size = mapFile.readUint32LE(); |
| | 349 | _rawAudioMap[offset] = size; |
| | 350 | } |
| | 351 | mapFile.close(); |
| | 352 | return _rawAudioMap.size(); |
| 317 | 353 | } |
| 318 | 354 | |
| 319 | 355 | void CompressSci::execute() { |
| … |
… |
void CompressSci::execute() {
|
| 325 | 361 | _inputSize = _input.size(); |
| 326 | 362 | |
| 327 | 363 | // First find out how many samples are in this file |
| 328 | | // We only support SOL audio and WAVE |
| 329 | | // We can't support games that use "raw" audio (would have to walk through audio map for those, which would |
| 330 | | // complicate this code - all talkie games that use this (kq5) don't use much space anyway, so not supporting |
| 331 | | // those isn't a big issue |
| 332 | 364 | |
| | 365 | _rawAudio = false; |
| 333 | 366 | _input.seek(0, SEEK_SET); |
| 334 | 367 | byte header[6]; |
| 335 | 368 | |
| … |
… |
void CompressSci::execute() {
|
| 343 | 376 | error("This resource file is already FLAC-compressed, aborting...\n"); |
| 344 | 377 | |
| 345 | 378 | int resourceCount = 0; |
| 346 | | do { |
| 347 | | recognizedDataType = detectData(header, false); |
| 348 | | if (!recognizedDataType) |
| 349 | | error("Unsupported data at offset %lx", _inputOffset); |
| 350 | | _input.seek(_inputEndOffset, SEEK_SET); |
| 351 | | _inputOffset = _inputEndOffset; |
| 352 | | resourceCount++; |
| 353 | | // We abort even, if file position is one below size because of pharkas resource.sfx |
| 354 | | if (_inputOffset >= _inputSize - 1) |
| 355 | | break; |
| | 379 | if (_input.size() == 0x05C9B000 or _input.size() == 0x0160E000) { |
| | 380 | warning("Size matches KQ5 or Jones in the Fast Lane audio file, assuming raw audio\n"); |
| | 381 | _rawAudio = true; |
| | 382 | resourceCount = parseRawAudioMap(); |
| | 383 | } else { |
| | 384 | do { |
| | 385 | recognizedDataType = detectData(header, false); |
| | 386 | if (!recognizedDataType) |
| | 387 | error("Unsupported data at offset %lx", _inputOffset); |
| | 388 | _input.seek(_inputEndOffset, SEEK_SET); |
| | 389 | _inputOffset = _inputEndOffset; |
| | 390 | resourceCount++; |
| | 391 | // We abort even, if file position is one below size because of pharkas resource.sfx |
| | 392 | if (_inputOffset >= _inputSize - 1) |
| | 393 | break; |
| 356 | 394 | |
| 357 | | _input.read_throwsOnError(&header, 6); |
| 358 | | } while (true); |
| | 395 | _input.read_throwsOnError(&header, 6); |
| | 396 | } while (true); |
| | 397 | } |
| 359 | 398 | |
| 360 | 399 | // This case happens on pharkas resource.sfx |
| 361 | 400 | if (_inputOffset != _inputSize) |
| … |
… |
void CompressSci::execute() {
|
| 394 | 433 | _input.seek(_inputOffset, SEEK_SET); |
| 395 | 434 | compressData(recognizedDataType); |
| 396 | 435 | |
| | 436 | // raw files are 0-padded to 2048 bytes |
| | 437 | if (recognizedDataType == kSciResourceDataTypeRaw and _inputEndOffset % 2048) |
| | 438 | _inputEndOffset = (((_inputEndOffset >> 11) + 1) << 11) & 0xffffffff; |
| | 439 | |
| 397 | 440 | // Seek inputfile to the end of the data |
| 398 | 441 | _input.seek(_inputEndOffset, SEEK_SET); |
| 399 | 442 | // Seek outputfile to mapping table |
diff --git a/engines/sci/compress_sci.h b/engines/sci/compress_sci.h
index 3c92d6f..e1e404a 100644
|
a
|
b
|
|
| 24 | 24 | #define COMPRESS_SCI_H |
| 25 | 25 | |
| 26 | 26 | #include "compress.h" |
| | 27 | #include <map> |
| 27 | 28 | |
| 28 | 29 | enum SciResourceDataType { |
| 29 | 30 | kSciResourceDataTypeUnknown = 0, |
| 30 | 31 | kSciResourceDataTypeWAVE = 1, |
| 31 | 32 | kSciResourceDataTypeSOL = 2, |
| 32 | | kSciResourceTypeTypeSync = 3 |
| | 33 | kSciResourceTypeTypeSync = 3, |
| | 34 | kSciResourceDataTypeRaw = 4 |
| 33 | 35 | }; |
| 34 | 36 | |
| 35 | 37 | class CompressSci : public CompressionTool { |
| … |
… |
public:
|
| 41 | 43 | protected: |
| 42 | 44 | SciResourceDataType detectData(byte *header, bool compressMode); |
| 43 | 45 | void compressData(SciResourceDataType dataType); |
| | 46 | uint parseRawAudioMap(); |
| 44 | 47 | |
| 45 | 48 | Common::File _input, _output; |
| 46 | 49 | int _inputOffset; |
| 47 | 50 | int _inputEndOffset; |
| 48 | 51 | int _inputSize; |
| 49 | 52 | int _outputOffset; |
| | 53 | bool _rawAudio; |
| | 54 | std::map<uint32,uint32> _rawAudioMap; |
| 50 | 55 | }; |
| 51 | 56 | |
| 52 | 57 | #endif |