// NOTE: Functions in these module are somewhat different from what can be seen // in IDA because of two new helper functions that deal with incoming bits. I // bet something like these were implemented via function-like macro in the // same manner zlib deals with bits. The pattern is so common in this module so // I made an exception and extracted it into separate functions to increase // readability. #include "sound_decoder.h" #include #include #include #define SOUND_DECODER_IN_BUFFER_SIZE (512) typedef int (*DECODINGPROC)(SoundDecoder* soundDecoder, int offset, int bits); static bool soundDecoderPrepare(SoundDecoder* a1, SoundDecoderReadProc* readProc, int fileHandle); static unsigned char soundDecoderReadNextChunk(SoundDecoder* a1); static void _init_pack_tables(); static int _ReadBand_Fail_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt0_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt3_16_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt17_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt18_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt19_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt20_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt21_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt22_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt23_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt24_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt26_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt27_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBand_Fmt29_(SoundDecoder* soundDecoder, int offset, int bits); static int _ReadBands_(SoundDecoder* ptr); static void _untransform_subband0(unsigned char* a1, unsigned char* a2, int a3, int a4); static void _untransform_subband(unsigned char* a1, unsigned char* a2, int a3, int a4); static void _untransform_all(SoundDecoder* a1); static inline void soundDecoderRequireBits(SoundDecoder* soundDecoder, int bits); static inline void soundDecoderDropBits(SoundDecoder* soundDecoder, int bits); // 0x51E328 static int gSoundDecodersCount = 0; // 0x51E32C static bool _inited_ = false; // 0x51E330 static DECODINGPROC _ReadBand_tbl[32] = { _ReadBand_Fmt0_, _ReadBand_Fail_, _ReadBand_Fail_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt3_16_, _ReadBand_Fmt17_, _ReadBand_Fmt18_, _ReadBand_Fmt19_, _ReadBand_Fmt20_, _ReadBand_Fmt21_, _ReadBand_Fmt22_, _ReadBand_Fmt23_, _ReadBand_Fmt24_, _ReadBand_Fail_, _ReadBand_Fmt26_, _ReadBand_Fmt27_, _ReadBand_Fail_, _ReadBand_Fmt29_, _ReadBand_Fail_, _ReadBand_Fail_, }; // 0x6AD960 static unsigned char _pack11_2[128]; // 0x6AD9E0 static unsigned char _pack3_3[32]; // 0x6ADA00 static unsigned short word_6ADA00[128]; // 0x6ADB00 static unsigned char* _AudioDecoder_scale0; // 0x6ADB04 static unsigned char* _AudioDecoder_scale_tbl; // 0x4D3BB0 static bool soundDecoderPrepare(SoundDecoder* soundDecoder, SoundDecoderReadProc* readProc, int fileHandle) { soundDecoder->readProc = readProc; soundDecoder->fd = fileHandle; soundDecoder->bufferIn = (unsigned char*)malloc(SOUND_DECODER_IN_BUFFER_SIZE); if (soundDecoder->bufferIn == NULL) { return false; } soundDecoder->bufferInSize = SOUND_DECODER_IN_BUFFER_SIZE; soundDecoder->remainingInSize = 0; return true; } // 0x4D3BE0 static unsigned char soundDecoderReadNextChunk(SoundDecoder* soundDecoder) { soundDecoder->remainingInSize = soundDecoder->readProc(soundDecoder->fd, soundDecoder->bufferIn, soundDecoder->bufferInSize); if (soundDecoder->remainingInSize == 0) { memset(soundDecoder->bufferIn, 0, soundDecoder->bufferInSize); soundDecoder->remainingInSize = soundDecoder->bufferInSize; } soundDecoder->nextIn = soundDecoder->bufferIn; soundDecoder->remainingInSize -= 1; return *soundDecoder->nextIn++; } // 0x4D3C78 static void _init_pack_tables() { int i; int j; int m; if (_inited_) { return; } for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { for (m = 0; m < 3; m++) { _pack3_3[i + j * 3 + m * 9] = i + j * 4 + m * 16; } } } for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { for (m = 0; m < 5; m++) { word_6ADA00[i + j * 5 + m * 25] = i + j * 8 + m * 64; } } } for (i = 0; i < 11; i++) { for (j = 0; j < 11; j++) { _pack11_2[i + j * 11] = i + j * 16; } } _inited_ = true; } // 0x4D3D9C static int _ReadBand_Fail_(SoundDecoder* soundDecoder, int offset, int bits) { return 0; } // 0x4D3DA0 static int _ReadBand_Fmt0_(SoundDecoder* soundDecoder, int offset, int bits) { int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { *p = 0; p += soundDecoder->field_24; i--; } return 1; } // 0x4D3DC8 static int _ReadBand_Fmt3_16_(SoundDecoder* soundDecoder, int offset, int bits) { int value; int v14; short* base = (short*)_AudioDecoder_scale0; base += (int)(UINT_MAX << (bits - 1)); int* p = (int*)soundDecoder->field_34; p += offset; v14 = (1 << bits) - 1; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, bits); value = soundDecoder->hold; soundDecoderDropBits(soundDecoder, bits); *p = base[v14 & value]; p += soundDecoder->field_24; i--; } return 1; } // 0x4D3E90 static int _ReadBand_Fmt17_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 3); int value = soundDecoder->hold & 0xFF; if (!(value & 0x01)) { soundDecoderDropBits(soundDecoder, 1); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else if (!(value & 0x02)) { soundDecoderDropBits(soundDecoder, 2); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else { soundDecoderDropBits(soundDecoder, 3); if (value & 0x04) { *p = base[1]; } else { *p = base[-1]; } p += soundDecoder->field_24; i--; } } return 1; } // 0x4D3F98 static int _ReadBand_Fmt18_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 2); int value = soundDecoder->hold; if (!(value & 0x01)) { soundDecoderDropBits(soundDecoder, 1); *p = 0; p += soundDecoder->field_24; if (--i == 0) { return 1; } } else { soundDecoderDropBits(soundDecoder, 2); if (value & 0x02) { *p = base[1]; } else { *p = base[-1]; } p += soundDecoder->field_24; i--; } } return 1; } // 0x4D4068 static int _ReadBand_Fmt19_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; base -= 1; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 5); int value = soundDecoder->hold & 0x1F; soundDecoderDropBits(soundDecoder, 5); value = _pack3_3[value]; *p = base[value & 0x03]; p += soundDecoder->field_24; if (--i == 0) { break; } *p = base[(value >> 2) & 0x03]; p += soundDecoder->field_24; if (--i == 0) { break; } *p = base[value >> 4]; p += soundDecoder->field_24; i--; } return 1; } // 0x4D4158 static int _ReadBand_Fmt20_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 4); int value = soundDecoder->hold & 0xFF; if (!(value & 0x01)) { soundDecoderDropBits(soundDecoder, 1); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else if (!(value & 0x02)) { soundDecoderDropBits(soundDecoder, 2); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else { soundDecoderDropBits(soundDecoder, 4); if (value & 0x08) { if (value & 0x04) { *p = base[2]; } else { *p = base[1]; } } else { if (value & 0x04) { *p = base[-1]; } else { *p = base[-2]; } } p += soundDecoder->field_24; i--; } } return 1; } // 0x4D4254 static int _ReadBand_Fmt21_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 3); int value = soundDecoder->hold & 0xFF; if (!(value & 0x01)) { soundDecoderDropBits(soundDecoder, 1); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else { soundDecoderDropBits(soundDecoder, 3); if (value & 0x04) { if (value & 0x02) { *p = base[2]; } else { *p = base[1]; } } else { if (value & 0x02) { *p = base[-1]; } else { *p = base[-2]; } } p += soundDecoder->field_24; i--; } } return 1; } // 0x4D4338 static int _ReadBand_Fmt22_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; base -= 2; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 7); int value = soundDecoder->hold & 0x7F; soundDecoderDropBits(soundDecoder, 7); value = word_6ADA00[value]; *p = base[value & 7]; p += soundDecoder->field_24; if (--i == 0) { break; } *p = base[((value >> 3) & 7)]; p += soundDecoder->field_24; if (--i == 0) { break; } *p = base[value >> 6]; p += soundDecoder->field_24; if (--i == 0) { break; } } return 1; } // 0x4D4434 static int _ReadBand_Fmt23_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 5); int value = soundDecoder->hold; if (!(value & 0x01)) { soundDecoderDropBits(soundDecoder, 1); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else if (!(value & 0x02)) { soundDecoderDropBits(soundDecoder, 2); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else if (!(value & 0x04)) { soundDecoderDropBits(soundDecoder, 4); if (value & 0x08) { *p = base[1]; } else { *p = base[-1]; } p += soundDecoder->field_24; if (--i == 0) { break; } } else { soundDecoderDropBits(soundDecoder, 5); value >>= 3; value &= 0x03; if (value >= 2) { value += 3; } *p = base[value - 3]; p += soundDecoder->field_24; i--; } } return 1; } // 0x4D4584 static int _ReadBand_Fmt24_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 4); int value = soundDecoder->hold & 0xFF; if (!(value & 0x01)) { soundDecoderDropBits(soundDecoder, 1); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else if (!(value & 0x02)) { soundDecoderDropBits(soundDecoder, 3); if (value & 0x04) { *p = base[1]; } else { *p = base[-1]; } p += soundDecoder->field_24; if (--i == 0) { break; } } else { soundDecoderDropBits(soundDecoder, 4); value >>= 2; value &= 0x03; if (value >= 2) { value += 3; } *p = base[value - 3]; p += soundDecoder->field_24; i--; } } return 1; } // 0x4D4698 static int _ReadBand_Fmt26_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 5); int value = soundDecoder->hold; if (!(value & 0x01)) { soundDecoderDropBits(soundDecoder, 1); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else if (!(value & 0x02)) { soundDecoderDropBits(soundDecoder, 2); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else { soundDecoderDropBits(soundDecoder, 5); value >>= 2; value &= 0x07; if (value >= 4) { value += 1; } *p = base[value - 4]; p += soundDecoder->field_24; i--; } } return 1; } // 0x4D47A4 static int _ReadBand_Fmt27_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 4); int value = soundDecoder->hold; if (!(value & 0x01)) { soundDecoderDropBits(soundDecoder, 1); *p = 0; p += soundDecoder->field_24; if (--i == 0) { break; } } else { soundDecoderDropBits(soundDecoder, 4); value >>= 1; value &= 0x07; if (value >= 4) { value += 1; } *p = base[value - 4]; p += soundDecoder->field_24; i--; } } return 1; } // 0x4D4870 static int _ReadBand_Fmt29_(SoundDecoder* soundDecoder, int offset, int bits) { short* base = (short*)_AudioDecoder_scale0; int* p = (int*)soundDecoder->field_34; p += offset; int i = soundDecoder->field_28; while (i != 0) { soundDecoderRequireBits(soundDecoder, 7); int value = soundDecoder->hold & 0x7F; soundDecoderDropBits(soundDecoder, 7); value = _pack11_2[value]; *p = base[(value & 0x0F) - 5]; p += soundDecoder->field_24; if (--i == 0) { break; } *p = base[(value >> 4) - 5]; p += soundDecoder->field_24; if (--i == 0) { break; } } return 1; } // 0x4D493C static int _ReadBands_(SoundDecoder* soundDecoder) { int v9; int v15; int v17; int v19; unsigned short* v18; int v21; DECODINGPROC fn; soundDecoderRequireBits(soundDecoder, 4); v9 = soundDecoder->hold & 0xF; soundDecoderDropBits(soundDecoder, 4); soundDecoderRequireBits(soundDecoder, 16); v15 = soundDecoder->hold & 0xFFFF; soundDecoderDropBits(soundDecoder, 16); v17 = 1 << v9; v18 = (unsigned short*)_AudioDecoder_scale0; v19 = v17; v21 = 0; while (v19--) { *v18++ = v21; v21 += v15; } v18 = (unsigned short*)_AudioDecoder_scale0; v19 = v17; v21 = -v15; while (v19--) { v18--; *v18 = v21; v21 -= v15; } _init_pack_tables(); for (int index = 0; index < soundDecoder->field_24; index++) { soundDecoderRequireBits(soundDecoder, 5); int bits = soundDecoder->hold & 0x1F; soundDecoderDropBits(soundDecoder, 5); fn = _ReadBand_tbl[bits]; if (!fn(soundDecoder, index, bits)) { return 0; } } return 1; } // 0x4D4ADC static void _untransform_subband0(unsigned char* a1, unsigned char* a2, int a3, int a4) { short* p; p = (short*)a2; p += a3; if (a4 == 2) { int i = a3; while (i != 0) { i--; } } else if (a4 == 4) { int v31 = a3; int* v9 = (int*)a2; v9 += a3; int* v10 = (int*)a2; v10 += a3 * 3; int* v11 = (int*)a2; v11 += a3 * 2; while (v31 != 0) { int* v33 = (int*)a2; int* v34 = (int*)a1; int v12 = *v34 >> 16; int v13 = *v33; *v33 = (int)(*(short*)v34) + 2 * v12 + v13; int v14 = *v9; *v9 = 2 * v13 - v12 - v14; int v15 = *v11; *v11 = 2 * v14 + v15 + v13; int v16 = *v10; *v10 = 2 * v15 - v14 - v16; v10++; v11++; v9++; *(short*)a1 = v15 & 0xFFFF; *(short*)(a1 + 2) = v16 & 0xFFFF; a1 += 4; a2 += 4; v31--; } } else { int v30 = a4 >> 1; int v32 = a3; while (v32 != 0) { int* v19 = (int*)a2; int v20; int v22; if (v30 & 0x01) { } else { v20 = (int)*(short*)a1; v22 = *(int*)a1 >> 16; } int v23 = v30 >> 1; while (--v23 != -1) { int v24 = *v19; *v19 += 2 * v22 + v20; v19 += a3; int v26 = *v19; *v19 = 2 * v24 - v22 - v26; v19 += a3; v20 = *v19; *v19 += 2 * v26 + v24; v19 += a3; v22 = *v19; *v19 = 2 * v20 - v26 - v22; v19 += a3; } *(short*)a1 = v20 & 0xFFFF; *(short*)(a1 + 2) = v22 & 0xFFFF; a1 += 4; a2 += 4; v32--; } } } // 0x4D4D1C static void _untransform_subband(unsigned char* a1, unsigned char* a2, int a3, int a4) { int v13; int* v14; int* v25; int* v26; int v15; int v16; int v17; int* v18; int v19; int* v20; int* v21; v26 = (int*)a1; v25 = (int*)a2; if (a4 == 4) { unsigned char* v4 = a2 + 4 * a3; unsigned char* v5 = a2 + 3 * a3; unsigned char* v6 = a2 + 2 * a3; int v7; int v8; int v9; int v10; int v11; while (a3--) { v7 = *(unsigned int*)(v26 + 4); v8 = *(unsigned int*)v25; *(unsigned int*)v25 = *(unsigned int*)v26 + 2 * v7; v9 = *(unsigned int*)v4; *(unsigned int*)v4 = 2 * v8 - v7 - v9; v10 = *(unsigned int*)v6; v5 += 4; *v6 += 2 * v9 + v8; v11 = *(unsigned int*)(v5 - 4); v6 += 4; *(unsigned int*)(v5 - 4) = 2 * v10 - v9 - v11; v4 += 4; *(unsigned int*)v26 = v10; *(unsigned int*)(v26 + 4) = v11; v26 += 2; v25 += 1; } } else { int v24 = a3; while (v24 != 0) { v13 = a4 >> 2; v14 = v25; v15 = v26[0]; v16 = v26[1]; while (--v13 != -1) { v17 = *v14; *v14 += 2 * v16 + v15; v18 = v14 + a3; v19 = *v18; *v18 = 2 * v17 - v16 - v19; v20 = v18 + a3; v15 = *v20; *v20 += 2 * v19 + v17; v21 = v20 + a3; v16 = *v21; *v21 = 2 * v15 - v19 - v16; v14 = v21 + a3; } v26[0] = v15; v26[1] = v16; v26 += 2; v25 += 1; v24--; } } } // 0x4D4E80 static void _untransform_all(SoundDecoder* soundDecoder) { int v8; unsigned char* ptr; int v3; int v4; unsigned char* j; int v6; int* v5; if (!soundDecoder->field_20) { return; } ptr = soundDecoder->field_34; v8 = soundDecoder->field_28; while (v8 > 0) { v3 = soundDecoder->field_24 >> 1; v4 = soundDecoder->field_38; if (v4 > v8) { v4 = v8; } v4 *= 2; _untransform_subband0(soundDecoder->field_30, ptr, v3, v4); v5 = (int*)ptr; for (v6 = 0; v6 < v4; v6++) { *v5 += 1; v5 += v3; } j = 4 * v3 + soundDecoder->field_30; while (1) { v3 >>= 1; v4 *= 2; if (v3 == 0) { break; } _untransform_subband(j, ptr, v3, v4); j += 8 * v3; } ptr += soundDecoder->field_3C * 4; v8 -= soundDecoder->field_38; } } // 0x4D4FA0 size_t soundDecoderDecode(SoundDecoder* soundDecoder, void* buffer, size_t size) { unsigned char* dest; unsigned char* v5; int v6; int v4; dest = (unsigned char*)buffer; v4 = 0; v5 = soundDecoder->field_4C; v6 = soundDecoder->field_50; size_t bytesRead; for (bytesRead = 0; bytesRead < size; bytesRead += 2) { if (!v6) { if (!soundDecoder->field_48) { break; } if (!_ReadBands_(soundDecoder)) { break; } _untransform_all(soundDecoder); soundDecoder->field_48 -= soundDecoder->field_2C; soundDecoder->field_4C = soundDecoder->field_34; soundDecoder->field_50 = soundDecoder->field_2C; if (soundDecoder->field_48 < 0) { soundDecoder->field_50 += soundDecoder->field_48; soundDecoder->field_48 = 0; } v5 = soundDecoder->field_4C; v6 = soundDecoder->field_50; } int v13 = *(int*)v5; v5 += 4; *(unsigned short*)(dest + bytesRead) = (v13 >> soundDecoder->field_20) & 0xFFFF; v6--; } soundDecoder->field_4C = v5; soundDecoder->field_50 = v6; return bytesRead; } // 0x4D5048 void soundDecoderFree(SoundDecoder* soundDecoder) { if (soundDecoder->bufferIn != NULL) { free(soundDecoder->bufferIn); } if (soundDecoder->field_30 != NULL) { free(soundDecoder->field_30); } if (soundDecoder->field_34 != NULL) { free(soundDecoder->field_34); } free(soundDecoder); gSoundDecodersCount--; if (gSoundDecodersCount == 0) { if (_AudioDecoder_scale_tbl != NULL) { free(_AudioDecoder_scale_tbl); _AudioDecoder_scale_tbl = NULL; } } } // 0x4D50A8 SoundDecoder* soundDecoderInit(SoundDecoderReadProc* readProc, int fileHandle, int* out_a3, int* out_a4, int* out_a5) { int v14; int v20; int v73; SoundDecoder* soundDecoder = (SoundDecoder*)malloc(sizeof(*soundDecoder)); if (soundDecoder == NULL) { return NULL; } memset(soundDecoder, 0, sizeof(*soundDecoder)); gSoundDecodersCount++; if (!soundDecoderPrepare(soundDecoder, readProc, fileHandle)) { goto L66; } soundDecoder->hold = 0; soundDecoder->bits = 0; soundDecoderRequireBits(soundDecoder, 24); v14 = soundDecoder->hold; soundDecoderDropBits(soundDecoder, 24); if ((v14 & 0xFFFFFF) != 0x32897) { goto L66; } soundDecoderRequireBits(soundDecoder, 8); v20 = soundDecoder->hold; soundDecoderDropBits(soundDecoder, 8); if (v20 != 1) { goto L66; } soundDecoderRequireBits(soundDecoder, 16); soundDecoder->field_48 = soundDecoder->hold & 0xFFFF; soundDecoderDropBits(soundDecoder, 16); soundDecoderRequireBits(soundDecoder, 16); soundDecoder->field_48 |= (soundDecoder->hold & 0xFFFF) << 16; soundDecoderDropBits(soundDecoder, 16); soundDecoderRequireBits(soundDecoder, 16); soundDecoder->field_40 = soundDecoder->hold & 0xFFFF; soundDecoderDropBits(soundDecoder, 16); soundDecoderRequireBits(soundDecoder, 16); soundDecoder->field_44 = soundDecoder->hold & 0xFFFF; soundDecoderDropBits(soundDecoder, 16); soundDecoderRequireBits(soundDecoder, 4); soundDecoder->field_20 = soundDecoder->hold & 0x0F; soundDecoderDropBits(soundDecoder, 4); soundDecoderRequireBits(soundDecoder, 12); soundDecoder->field_24 = 1 << soundDecoder->field_20; soundDecoder->field_28 = soundDecoder->hold & 0x0FFF; soundDecoder->field_2C = soundDecoder->field_28 * soundDecoder->field_24; soundDecoderDropBits(soundDecoder, 12); if (soundDecoder->field_20 != 0) { v73 = 3 * soundDecoder->field_24 / 2 - 2; } else { v73 = 0; } soundDecoder->field_38 = 2048 / soundDecoder->field_24 - 2; if (soundDecoder->field_38 < 1) { soundDecoder->field_38 = 1; } soundDecoder->field_3C = soundDecoder->field_38 * soundDecoder->field_24; if (v73 != 0) { soundDecoder->field_30 = (unsigned char*)malloc(sizeof(unsigned char*) * v73); if (soundDecoder->field_30 == NULL) { goto L66; } memset(soundDecoder->field_30, 0, sizeof(unsigned char*) * v73); } soundDecoder->field_34 = (unsigned char*)malloc(sizeof(unsigned char*) * soundDecoder->field_2C); if (soundDecoder->field_34 == NULL) { goto L66; } soundDecoder->field_50 = 0; if (gSoundDecodersCount == 1) { _AudioDecoder_scale_tbl = (unsigned char*)malloc(0x20000); _AudioDecoder_scale0 = _AudioDecoder_scale_tbl + 0x10000; } *out_a3 = soundDecoder->field_40; *out_a4 = soundDecoder->field_44; *out_a5 = soundDecoder->field_48; return soundDecoder; L66: soundDecoderFree(soundDecoder); *out_a3 = 0; *out_a4 = 0; *out_a5 = 0; return 0; } static inline void soundDecoderRequireBits(SoundDecoder* soundDecoder, int bits) { while (soundDecoder->bits < bits) { soundDecoder->remainingInSize--; unsigned char ch; if (soundDecoder->remainingInSize < 0) { ch = soundDecoderReadNextChunk(soundDecoder); } else { ch = *soundDecoder->nextIn++; } soundDecoder->hold |= ch << soundDecoder->bits; soundDecoder->bits += 8; } } static inline void soundDecoderDropBits(SoundDecoder* soundDecoder, int bits) { soundDecoder->hold >>= bits; soundDecoder->bits -= bits; }