2022-05-19 01:51:26 -07:00
|
|
|
#include "audio.h"
|
|
|
|
|
|
|
|
#include "db.h"
|
|
|
|
#include "debug.h"
|
|
|
|
#include "memory_manager.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:36:13 -07:00
|
|
|
static bool _defaultCompressionFunc(char* filePath);
|
|
|
|
static int audioSoundDecoderReadHandler(int fileHandle, void* buf, unsigned int size);
|
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
// 0x5108BC
|
2022-06-18 05:36:13 -07:00
|
|
|
static AudioFileIsCompressedProc* _queryCompressedFunc = _defaultCompressionFunc;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x56CB00
|
2022-06-18 05:36:13 -07:00
|
|
|
static int gAudioListLength;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x56CB04
|
2022-06-18 05:36:13 -07:00
|
|
|
static AudioFile* gAudioList;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x41A2B0
|
2022-06-18 05:36:13 -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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x41A2D0
|
2022-06-18 05:36:13 -07:00
|
|
|
static int audioSoundDecoderReadHandler(int fileHandle, void* buffer, unsigned int size)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
2022-07-05 01:00:55 -07:00
|
|
|
return fileRead(buffer, 1, size, (File*)intToPtr(fileHandle));
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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) {
|
2022-05-21 08:22:03 -07:00
|
|
|
gAudioList = (AudioFile*)internal_realloc_safe(gAudioList, sizeof(*gAudioList) * (gAudioListLength + 1), __FILE__, __LINE__); // "..\int\audio.c", 216
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2022-05-21 08:22:03 -07:00
|
|
|
gAudioList = (AudioFile*)internal_malloc_safe(sizeof(*gAudioList), __FILE__, __LINE__); // "..\int\audio.c", 218
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
gAudioListLength++;
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioFile* audioFile = &(gAudioList[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(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]);
|
2022-07-05 01:00:55 -07:00
|
|
|
fileClose((File*)intToPtr(audioFile->fileHandle, true));
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
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 {
|
2022-07-05 01:00:55 -07:00
|
|
|
bytesRead = fileRead(buffer, 1, size, (File*)intToPtr(audioFile->fileHandle));
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
audioFile->position += bytesRead;
|
|
|
|
|
|
|
|
return bytesRead;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x41A5E0
|
2022-05-21 08:22:03 -07:00
|
|
|
long audioSeek(int fileHandle, long offset, int origin)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
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);
|
2022-07-05 01:00:55 -07:00
|
|
|
fileSeek((File*)intToPtr(audioFile->fileHandle), 0, SEEK_SET);
|
2022-05-19 01:51:26 -07:00
|
|
|
audioFile->soundDecoder = soundDecoderInit(audioSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize));
|
|
|
|
audioFile->position = 0;
|
|
|
|
audioFile->fileSize *= 2;
|
|
|
|
|
|
|
|
if (pos != 0) {
|
2022-05-21 08:22:03 -07:00
|
|
|
buf = (unsigned char*)internal_malloc_safe(4096, __FILE__, __LINE__); // "..\int\audio.c", 361
|
2022-05-19 01:51:26 -07:00
|
|
|
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 {
|
2022-05-21 08:22:03 -07:00
|
|
|
buf = (unsigned char*)internal_malloc_safe(1024, __FILE__, __LINE__); // "..\int\audio.c", 321
|
2022-05-19 01:51:26 -07:00
|
|
|
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 {
|
2022-07-05 01:00:55 -07:00
|
|
|
return fileSeek((File*)intToPtr(audioFile->fileHandle), offset, origin);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|