1259 lines
29 KiB
C++
1259 lines
29 KiB
C++
// 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 <limits.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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 += 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;
|
|
}
|