fallout2-ce/src/audio_file.cc

252 lines
6.7 KiB
C++
Raw Normal View History

2022-05-19 01:51:26 -07:00
#include "audio_file.h"
#include "debug.h"
#include "memory_manager.h"
2022-05-28 02:34:49 -07:00
#include "platform_compat.h"
2022-07-05 01:00:55 -07:00
#include "pointer_registry.h"
2022-05-19 01:51:26 -07:00
#include "sound.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
2022-06-18 05:39:21 -07:00
static bool _defaultCompressionFunc__(char* filePath);
static int audioFileSoundDecoderReadHandler(int fileHandle, void* buffer, unsigned int size);
2022-05-19 01:51:26 -07:00
// 0x5108C0
2022-06-18 05:39:21 -07:00
static AudioFileIsCompressedProc* _queryCompressedFunc_2 = _defaultCompressionFunc__;
2022-05-19 01:51:26 -07:00
// 0x56CB10
2022-06-18 05:39:21 -07:00
static AudioFile* gAudioFileList;
2022-05-19 01:51:26 -07:00
// 0x56CB14
2022-06-18 05:39:21 -07:00
static int gAudioFileListLength;
2022-05-19 01:51:26 -07:00
// 0x41A850
2022-06-18 05:39:21 -07:00
static bool _defaultCompressionFunc__(char* filePath)
2022-05-19 01:51:26 -07:00
{
char* pch = strrchr(filePath, '.');
if (pch != NULL) {
strcpy(pch + 1, "war");
}
return false;
}
// 0x41A870
2022-06-18 05:39:21 -07:00
static int audioFileSoundDecoderReadHandler(int fileHandle, void* buffer, unsigned int size)
2022-05-19 01:51:26 -07:00
{
2022-07-05 01:00:55 -07:00
return fread(buffer, 1, size, (FILE*)intToPtr(fileHandle));
2022-05-19 01:51:26 -07:00
}
// 0x41A88C
int audioFileOpen(const char* fname, int flags, ...)
{
2022-05-28 02:34:49 -07:00
char path[COMPAT_MAX_PATH];
2022-05-19 01:51:26 -07:00
strcpy(path, fname);
int compression;
if (_queryCompressedFunc_2(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 & 0x01) {
*pm++ = 'w';
} else if (flags & 0x02) {
*pm++ = 'w';
*pm++ = '+';
} else {
*pm++ = 'r';
}
if (flags & 0x0100) {
*pm++ = 't';
} else if (flags & 0x0200) {
*pm++ = 'b';
}
FILE* stream = compat_fopen(path, mode);
2022-05-19 01:51:26 -07:00
if (stream == NULL) {
return -1;
}
int index;
for (index = 0; index < gAudioFileListLength; index++) {
if ((gAudioFileList[index].flags & AUDIO_FILE_IN_USE) == 0) {
break;
}
}
if (index == gAudioFileListLength) {
if (gAudioFileList != NULL) {
2022-05-21 08:22:03 -07:00
gAudioFileList = (AudioFile*)internal_realloc_safe(gAudioFileList, sizeof(*gAudioFileList) * (gAudioFileListLength + 1), __FILE__, __LINE__); // "..\int\audiof.c", 207
2022-05-19 01:51:26 -07:00
} else {
2022-05-21 08:22:03 -07:00
gAudioFileList = (AudioFile*)internal_malloc_safe(sizeof(*gAudioFileList), __FILE__, __LINE__); // "..\int\audiof.c", 209
2022-05-19 01:51:26 -07:00
}
gAudioFileListLength++;
}
AudioFile* audioFile = &(gAudioFileList[index]);
audioFile->flags = AUDIO_FILE_IN_USE;
2022-07-05 01:00:55 -07:00
audioFile->fileHandle = ptrToInt(stream);
2022-05-19 01:51:26 -07:00
if (compression == 2) {
audioFile->flags |= AUDIO_FILE_COMPRESSED;
audioFile->soundDecoder = soundDecoderInit(audioFileSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize));
audioFile->fileSize *= 2;
} else {
2022-08-31 21:37:00 -07:00
audioFile->fileSize = getFileSize(stream);
2022-05-19 01:51:26 -07:00
}
audioFile->position = 0;
return index + 1;
}
// 0x41AAA0
int audioFileClose(int fileHandle)
{
AudioFile* audioFile = &(gAudioFileList[fileHandle - 1]);
2022-07-05 01:00:55 -07:00
fclose((FILE*)intToPtr(audioFile->fileHandle, true));
2022-05-19 01:51:26 -07:00
if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) {
soundDecoderFree(audioFile->soundDecoder);
}
// Reset audio file (which also resets it's use flag).
memset(audioFile, 0, sizeof(*audioFile));
return 0;
}
// 0x41AB08
int audioFileRead(int fileHandle, void* buffer, unsigned int size)
{
AudioFile* ptr = &(gAudioFileList[fileHandle - 1]);
int bytesRead;
if ((ptr->flags & AUDIO_FILE_COMPRESSED) != 0) {
bytesRead = soundDecoderDecode(ptr->soundDecoder, buffer, size);
} else {
2022-07-05 01:00:55 -07:00
bytesRead = fread(buffer, 1, size, (FILE*)intToPtr(ptr->fileHandle));
2022-05-19 01:51:26 -07:00
}
ptr->position += bytesRead;
return bytesRead;
}
// 0x41AB74
2022-05-21 08:22:03 -07:00
long audioFileSeek(int fileHandle, long offset, int origin)
2022-05-19 01:51:26 -07:00
{
void* buf;
int remaining;
int a4;
AudioFile* audioFile = &(gAudioFileList[fileHandle - 1]);
switch (origin) {
case SEEK_SET:
a4 = offset;
break;
case SEEK_CUR:
a4 = audioFile->fileSize + offset;
break;
case SEEK_END:
a4 = audioFile->position + offset;
break;
default:
assert(false && "Should be unreachable");
}
if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) {
if (a4 <= audioFile->position) {
soundDecoderFree(audioFile->soundDecoder);
2022-07-05 01:00:55 -07:00
fseek((FILE*)intToPtr(audioFile->fileHandle), 0, 0);
2022-05-19 01:51:26 -07:00
audioFile->soundDecoder = soundDecoderInit(audioFileSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize));
audioFile->fileSize *= 2;
audioFile->position = 0;
if (a4) {
buf = internal_malloc_safe(4096, __FILE__, __LINE__); // "..\int\audiof.c", 364
while (a4 > 4096) {
audioFileRead(fileHandle, buf, 4096);
a4 -= 4096;
}
if (a4 != 0) {
audioFileRead(fileHandle, buf, a4);
}
internal_free_safe(buf, __FILE__, __LINE__); // "..\int\audiof.c", 370
}
} else {
buf = internal_malloc_safe(0x400, __FILE__, __LINE__); // "..\int\audiof.c", 316
remaining = audioFile->position - a4;
while (remaining > 1024) {
audioFileRead(fileHandle, buf, 1024);
remaining -= 1024;
}
if (remaining != 0) {
audioFileRead(fileHandle, buf, remaining);
}
// TODO: Obiously leaks memory.
}
return audioFile->position;
}
2022-07-05 01:00:55 -07:00
return fseek((FILE*)intToPtr(audioFile->fileHandle), offset, origin);
2022-05-19 01:51:26 -07:00
}
// 0x41AD20
long audioFileGetSize(int fileHandle)
{
AudioFile* audioFile = &(gAudioFileList[fileHandle - 1]);
return audioFile->fileSize;
}
// 0x41AD3C
long audioFileTell(int fileHandle)
{
AudioFile* audioFile = &(gAudioFileList[fileHandle - 1]);
return audioFile->position;
}
// AudiofWrite
// 0x41AD58
int audioFileWrite(int fileHandle, const void* buffer, unsigned int size)
{
debugPrint("AudiofWrite shouldn't be ever called\n");
return 0;
}
// 0x41AD68
int audioFileInit(AudioFileIsCompressedProc* isCompressedProc)
{
_queryCompressedFunc_2 = isCompressedProc;
gAudioFileList = NULL;
gAudioFileListLength = 0;
return soundSetDefaultFileIO(audioFileOpen, audioFileClose, audioFileRead, audioFileWrite, audioFileSeek, audioFileTell, audioFileGetSize);
}
// 0x41ADAC
void audioFileExit()
{
if (gAudioFileList != NULL) {
internal_free_safe(gAudioFileList, __FILE__, __LINE__); // "..\int\audiof.c", 405
}
gAudioFileListLength = 0;
gAudioFileList = NULL;
}