Fix missing speech in some Russian localizations

Closes #246
This commit is contained in:
Alexander Batalov 2023-04-11 14:03:55 +03:00
parent 6d1273d325
commit a2eabd668b
1 changed files with 67 additions and 33 deletions

View File

@ -34,13 +34,15 @@ static int ReadBand_Fmt24(SoundDecoder* soundDecoder, int offset, int bits);
static int ReadBand_Fmt26(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_Fmt27(SoundDecoder* soundDecoder, int offset, int bits);
static int ReadBand_Fmt29(SoundDecoder* soundDecoder, int offset, int bits); static int ReadBand_Fmt29(SoundDecoder* soundDecoder, int offset, int bits);
static int ReadBands(SoundDecoder* ptr); static bool ReadBands(SoundDecoder* soundDecoder);
static void untransform_subband0(unsigned char* a1, unsigned char* a2, int a3, int a4); 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_subband(unsigned char* a1, unsigned char* a2, int a3, int a4);
static void untransform_all(SoundDecoder* soundDecoder); static void untransform_all(SoundDecoder* soundDecoder);
static bool soundDecoderFill(SoundDecoder* soundDecoder);
static inline void soundDecoderRequireBits(SoundDecoder* soundDecoder, int bits); static inline void soundDecoderRequireBits(SoundDecoder* soundDecoder, int bits);
static inline void soundDecoderDropBits(SoundDecoder* soundDecoder, int bits); static inline void soundDecoderDropBits(SoundDecoder* soundDecoder, int bits);
static int ReadBand_Fmt31(SoundDecoder* soundDecoder, int offset, int bits);
// 0x51E328 // 0x51E328
static int gSoundDecodersCount = 0; static int gSoundDecodersCount = 0;
@ -78,7 +80,7 @@ static ReadBandFunc _ReadBand_tbl[32] = {
ReadBand_Fail, ReadBand_Fail,
ReadBand_Fmt29, ReadBand_Fmt29,
ReadBand_Fail, ReadBand_Fail,
ReadBand_Fail, ReadBand_Fmt31,
}; };
// 0x6AD960 // 0x6AD960
@ -751,7 +753,7 @@ static int ReadBand_Fmt29(SoundDecoder* soundDecoder, int offset, int bits)
} }
// 0x4D493C // 0x4D493C
static int ReadBands(SoundDecoder* soundDecoder) static bool ReadBands(SoundDecoder* soundDecoder)
{ {
int v9; int v9;
int v15; int v15;
@ -797,10 +799,10 @@ static int ReadBands(SoundDecoder* soundDecoder)
fn = _ReadBand_tbl[bits]; fn = _ReadBand_tbl[bits];
if (!fn(soundDecoder, index, bits)) { if (!fn(soundDecoder, index, bits)) {
return 0; return false;
} }
} }
return 1; return true;
} }
// 0x4D4ADC // 0x4D4ADC
@ -1043,53 +1045,67 @@ static void untransform_all(SoundDecoder* soundDecoder)
} }
} }
// NOTE: Inlined.
//
// 0x4D4F58
static bool soundDecoderFill(SoundDecoder* soundDecoder)
{
// CE: Implementation is slightly different. `ReadBands` now handles new
// Fmt31 used in some Russian localizations. The appropriate handler acts as
// both decoder and transformer, so there is no need to untransform bands
// once again. This approach assumes band 31 is never used by standard acms
// and mods.
if (ReadBands(soundDecoder)) {
untransform_all(soundDecoder);
}
soundDecoder->file_cnt -= soundDecoder->total_samples;
soundDecoder->samp_ptr = soundDecoder->samples;
soundDecoder->samp_cnt = soundDecoder->total_samples;
if (soundDecoder->file_cnt < 0) {
soundDecoder->samp_cnt += soundDecoder->file_cnt;
soundDecoder->file_cnt = 0;
}
return true;
}
// 0x4D4FA0 // 0x4D4FA0
size_t soundDecoderDecode(SoundDecoder* soundDecoder, void* buffer, size_t size) size_t soundDecoderDecode(SoundDecoder* soundDecoder, void* buffer, size_t size)
{ {
unsigned char* dest; unsigned char* dest;
unsigned char* v5; unsigned char* samp_ptr;
int v6; int samp_cnt;
int v4;
dest = (unsigned char*)buffer; dest = (unsigned char*)buffer;
v4 = 0; samp_ptr = soundDecoder->samp_ptr;
v5 = soundDecoder->samp_ptr; samp_cnt = soundDecoder->samp_cnt;
v6 = soundDecoder->samp_cnt;
size_t bytesRead; size_t bytesRead;
for (bytesRead = 0; bytesRead < size; bytesRead += 2) { for (bytesRead = 0; bytesRead < size; bytesRead += 2) {
if (!v6) { if (samp_cnt == 0) {
if (!soundDecoder->file_cnt) { if (soundDecoder->file_cnt == 0) {
break; break;
} }
if (!ReadBands(soundDecoder)) { // NOTE: Uninline.
if (!soundDecoderFill(soundDecoder)) {
break; break;
} }
untransform_all(soundDecoder); samp_ptr = soundDecoder->samp_ptr;
samp_cnt = soundDecoder->samp_cnt;
soundDecoder->file_cnt -= soundDecoder->total_samples;
soundDecoder->samp_ptr = soundDecoder->samples;
soundDecoder->samp_cnt = soundDecoder->total_samples;
if (soundDecoder->file_cnt < 0) {
soundDecoder->samp_cnt += soundDecoder->file_cnt;
soundDecoder->file_cnt = 0;
}
v5 = soundDecoder->samp_ptr;
v6 = soundDecoder->samp_cnt;
} }
int v13 = *(int*)v5; int sample = *(int*)samp_ptr;
v5 += 4; samp_ptr += 4;
*(unsigned short*)(dest + bytesRead) = (v13 >> soundDecoder->levels) & 0xFFFF; *(unsigned short*)(dest + bytesRead) = (sample >> soundDecoder->levels) & 0xFFFF;
v6--; samp_cnt--;
} }
soundDecoder->samp_ptr = v5; soundDecoder->samp_ptr = samp_ptr;
soundDecoder->samp_cnt = v6; soundDecoder->samp_cnt = samp_cnt;
return bytesRead; return bytesRead;
} }
@ -1259,4 +1275,22 @@ static inline void soundDecoderDropBits(SoundDecoder* soundDecoder, int bits)
soundDecoder->bits -= bits; soundDecoder->bits -= bits;
} }
static int ReadBand_Fmt31(SoundDecoder* soundDecoder, int offset, int bits)
{
int* samples = (int*)soundDecoder->samples;
int remaining_samples = soundDecoder->total_samples;
while (remaining_samples != 0) {
soundDecoderRequireBits(soundDecoder, 16);
int value = soundDecoder->hold & 0xFFFF;
soundDecoderDropBits(soundDecoder, 16);
*samples++ = (value << 16) >> (16 - soundDecoder->levels);
remaining_samples--;
}
return 0;
}
} // namespace fallout } // namespace fallout