fallout2-ce/src/audio.cc

251 lines
6.3 KiB
C++

#include "audio.h"
#include "db.h"
#include "debug.h"
#include "memory_manager.h"
#include "sound.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
// 0x5108BC
AudioFileIsCompressedProc* _queryCompressedFunc = _defaultCompressionFunc;
// 0x56CB00
int gAudioListLength;
// 0x56CB04
AudioFile* gAudioList;
// 0x41A2B0
bool _defaultCompressionFunc(char* filePath)
{
char* pch = strrchr(filePath, '.');
if (pch != NULL) {
strcpy(pch + 1, "war");
}
return false;
}
// 0x41A2D0
int audioSoundDecoderReadHandler(int fileHandle, void* buffer, unsigned int size)
{
return fileRead(buffer, 1, size, (File*)fileHandle);
}
// AudioOpen
// 0x41A2EC
int audioOpen(const char* fname, int flags, ...)
{
char path[80];
sprintf(path, fname);
int compression;
if (_queryCompressedFunc(path)) {
compression = 2;
} else {
compression = 0;
}
char mode[4];
memset(mode, 0, 4);
// NOTE: Original implementation is slightly different, it uses separate
// variable to track index where to set 't' and 'b'.
char* pm = mode;
if (flags & 1) {
*pm++ = 'w';
} else if (flags & 2) {
*pm++ = 'w';
*pm++ = '+';
} else {
*pm++ = 'r';
}
if (flags & 0x100) {
*pm++ = 't';
} else if (flags & 0x200) {
*pm++ = 'b';
}
File* stream = fileOpen(path, mode);
if (stream == NULL) {
debugPrint("AudioOpen: Couldn't open %s for read\n", path);
return -1;
}
int index;
for (index = 0; index < gAudioListLength; index++) {
if ((gAudioList[index].flags & AUDIO_FILE_IN_USE) == 0) {
break;
}
}
if (index == gAudioListLength) {
if (gAudioList != NULL) {
gAudioList = (AudioFile*)internal_realloc_safe(gAudioList, sizeof(*gAudioList) * (gAudioListLength + 1), __FILE__, __LINE__); // "..\int\audio.c", 216
} else {
gAudioList = (AudioFile*)internal_malloc_safe(sizeof(*gAudioList), __FILE__, __LINE__); // "..\int\audio.c", 218
}
gAudioListLength++;
}
AudioFile* audioFile = &(gAudioList[index]);
audioFile->flags = AUDIO_FILE_IN_USE;
audioFile->fileHandle = (int)stream;
if (compression == 2) {
audioFile->flags |= AUDIO_FILE_COMPRESSED;
audioFile->soundDecoder = soundDecoderInit(audioSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize));
audioFile->fileSize *= 2;
} else {
audioFile->fileSize = fileGetSize(stream);
}
audioFile->position = 0;
return index + 1;
}
// 0x41A50C
int audioClose(int fileHandle)
{
AudioFile* audioFile = &(gAudioList[fileHandle - 1]);
fileClose((File*)audioFile->fileHandle);
if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) {
soundDecoderFree(audioFile->soundDecoder);
}
memset(audioFile, 0, sizeof(AudioFile));
return 0;
}
// 0x41A574
int audioRead(int fileHandle, void* buffer, unsigned int size)
{
AudioFile* audioFile = &(gAudioList[fileHandle - 1]);
int bytesRead;
if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) {
bytesRead = soundDecoderDecode(audioFile->soundDecoder, buffer, size);
} else {
bytesRead = fileRead(buffer, 1, size, (File*)audioFile->fileHandle);
}
audioFile->position += bytesRead;
return bytesRead;
}
// 0x41A5E0
long audioSeek(int fileHandle, long offset, int origin)
{
int pos;
unsigned char* buf;
int v10;
AudioFile* audioFile = &(gAudioList[fileHandle - 1]);
switch (origin) {
case SEEK_SET:
pos = offset;
break;
case SEEK_CUR:
pos = offset + audioFile->position;
break;
case SEEK_END:
pos = offset + audioFile->fileSize;
break;
default:
assert(false && "Should be unreachable");
}
if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) {
if (pos < audioFile->position) {
soundDecoderFree(audioFile->soundDecoder);
fileSeek((File*)audioFile->fileHandle, 0, SEEK_SET);
audioFile->soundDecoder = soundDecoderInit(audioSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize));
audioFile->position = 0;
audioFile->fileSize *= 2;
if (pos != 0) {
buf = (unsigned char*)internal_malloc_safe(4096, __FILE__, __LINE__); // "..\int\audio.c", 361
while (pos > 4096) {
pos -= 4096;
audioRead(fileHandle, buf, 4096);
}
if (pos != 0) {
audioRead(fileHandle, buf, pos);
}
internal_free_safe(buf, __FILE__, __LINE__); // // "..\int\audio.c", 367
}
} else {
buf = (unsigned char*)internal_malloc_safe(1024, __FILE__, __LINE__); // "..\int\audio.c", 321
v10 = audioFile->position - pos;
while (v10 > 1024) {
v10 -= 1024;
audioRead(fileHandle, buf, 1024);
}
if (v10 != 0) {
audioRead(fileHandle, buf, v10);
}
// TODO: Probably leaks memory.
}
return audioFile->position;
} else {
return fileSeek((File*)audioFile->fileHandle, offset, origin);
}
}
// 0x41A78C
long audioGetSize(int fileHandle)
{
AudioFile* audioFile = &(gAudioList[fileHandle - 1]);
return audioFile->fileSize;
}
// 0x41A7A8
long audioTell(int fileHandle)
{
AudioFile* audioFile = &(gAudioList[fileHandle - 1]);
return audioFile->position;
}
// AudioWrite
// 0x41A7C4
int audioWrite(int handle, const void* buf, unsigned int size)
{
debugPrint("AudioWrite shouldn't be ever called\n");
return 0;
}
// 0x41A7D4
int audioInit(AudioFileIsCompressedProc* isCompressedProc)
{
_queryCompressedFunc = isCompressedProc;
gAudioList = NULL;
gAudioListLength = 0;
return soundSetDefaultFileIO(audioOpen, audioClose, audioRead, audioWrite, audioSeek, audioTell, audioGetSize);
}
// 0x41A818
void audioExit()
{
if (gAudioList != NULL) {
internal_free_safe(gAudioList, __FILE__, __LINE__); // "..\int\audio.c", 406
}
gAudioListLength = 0;
gAudioList = NULL;
}