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,31 +1045,19 @@ static void untransform_all(SoundDecoder* soundDecoder)
} }
} }
// 0x4D4FA0 // NOTE: Inlined.
size_t soundDecoderDecode(SoundDecoder* soundDecoder, void* buffer, size_t size) //
// 0x4D4F58
static bool soundDecoderFill(SoundDecoder* soundDecoder)
{ {
unsigned char* dest; // CE: Implementation is slightly different. `ReadBands` now handles new
unsigned char* v5; // Fmt31 used in some Russian localizations. The appropriate handler acts as
int v6; // both decoder and transformer, so there is no need to untransform bands
int v4; // once again. This approach assumes band 31 is never used by standard acms
// and mods.
dest = (unsigned char*)buffer; if (ReadBands(soundDecoder)) {
v4 = 0;
v5 = soundDecoder->samp_ptr;
v6 = soundDecoder->samp_cnt;
size_t bytesRead;
for (bytesRead = 0; bytesRead < size; bytesRead += 2) {
if (!v6) {
if (!soundDecoder->file_cnt) {
break;
}
if (!ReadBands(soundDecoder)) {
break;
}
untransform_all(soundDecoder); untransform_all(soundDecoder);
}
soundDecoder->file_cnt -= soundDecoder->total_samples; soundDecoder->file_cnt -= soundDecoder->total_samples;
soundDecoder->samp_ptr = soundDecoder->samples; soundDecoder->samp_ptr = soundDecoder->samples;
@ -1078,18 +1068,44 @@ size_t soundDecoderDecode(SoundDecoder* soundDecoder, void* buffer, size_t size)
soundDecoder->file_cnt = 0; soundDecoder->file_cnt = 0;
} }
v5 = soundDecoder->samp_ptr; return true;
v6 = soundDecoder->samp_cnt; }
// 0x4D4FA0
size_t soundDecoderDecode(SoundDecoder* soundDecoder, void* buffer, size_t size)
{
unsigned char* dest;
unsigned char* samp_ptr;
int samp_cnt;
dest = (unsigned char*)buffer;
samp_ptr = soundDecoder->samp_ptr;
samp_cnt = soundDecoder->samp_cnt;
size_t bytesRead;
for (bytesRead = 0; bytesRead < size; bytesRead += 2) {
if (samp_cnt == 0) {
if (soundDecoder->file_cnt == 0) {
break;
} }
int v13 = *(int*)v5; // NOTE: Uninline.
v5 += 4; if (!soundDecoderFill(soundDecoder)) {
*(unsigned short*)(dest + bytesRead) = (v13 >> soundDecoder->levels) & 0xFFFF; break;
v6--;
} }
soundDecoder->samp_ptr = v5; samp_ptr = soundDecoder->samp_ptr;
soundDecoder->samp_cnt = v6; samp_cnt = soundDecoder->samp_cnt;
}
int sample = *(int*)samp_ptr;
samp_ptr += 4;
*(unsigned short*)(dest + bytesRead) = (sample >> soundDecoder->levels) & 0xFFFF;
samp_cnt--;
}
soundDecoder->samp_ptr = samp_ptr;
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