devilutionX/Source/wave.cpp
Anders Jenbo 20621a0642
add all.h and use in place of diablo.h (#2005)
Now diablo.h is treated in the same way as all other header files of
Source, as it only contains the declarations of global variables and
functions of diablo.cpp.

Besides consistency, this also enables mods to include diablo.h just
like any other header file without having to include every header file
(and without having to include C++ specific aspects of the now all.h).
2020-02-14 13:12:54 +01:00

212 lines
5.1 KiB
C++

#include "all.h"
#include "../3rdParty/Storm/Source/storm.h"
BOOL WCloseFile(HANDLE file)
{
return SFileCloseFile(file);
}
LONG WGetFileSize(HANDLE hsFile, DWORD *lpFileSizeHigh)
{
DWORD retry = 0;
LONG ret;
while ((ret = SFileGetFileSize(hsFile, lpFileSizeHigh)) == 0)
WGetFileArchive(hsFile, &retry, NULL);
return ret;
}
void WGetFileArchive(HANDLE hsFile, DWORD *retries, const char *FileName)
{
HANDLE archive;
if (*retries >= 5)
FileErrDlg(FileName);
if (hsFile && SFileGetFileArchive(hsFile, &archive) && archive != diabdat_mpq) {
Sleep(20);
(*retries)++;
} else if (!InsertCDDlg())
FileErrDlg(FileName);
}
BOOL WOpenFile(const char *FileName, HANDLE *phsFile, BOOL mayNotExist)
{
DWORD retry = 0;
while (1) {
if (SFileOpenFile(FileName, phsFile))
return TRUE;
if (mayNotExist && SErrGetLastError() == ERROR_FILE_NOT_FOUND)
break;
WGetFileArchive(NULL, &retry, FileName);
}
return FALSE;
}
void WReadFile(HANDLE hsFile, LPVOID buf, DWORD to_read)
{
DWORD retry = 0;
DWORD readed;
int initial_pos = WSetFilePointer(hsFile, 0, NULL, FILE_CURRENT);
while (!SFileReadFile(hsFile, buf, to_read, &readed, NULL)) {
WGetFileArchive(hsFile, &retry, NULL);
WSetFilePointer(hsFile, initial_pos, NULL, FILE_BEGIN);
}
}
int WSetFilePointer(HANDLE file1, int offset, HANDLE file2, int whence)
{
DWORD retry = 0;
int result;
while (1) {
result = SFileSetFilePointer(file1, offset, file2, whence);
if (result != -1)
break;
WGetFileArchive(file1, &retry, NULL);
}
return result;
}
BOOL LoadWaveFormat(HANDLE hsFile, WAVEFORMATEX *pwfx)
{
BOOL ret;
MEMFILE wave_file;
AllocateMemFile(hsFile, &wave_file, 0);
ret = ReadWaveFile(&wave_file, pwfx, NULL);
FreeMemFile(&wave_file);
return ret;
}
void *AllocateMemFile(HANDLE hsFile, MEMFILE *pMemFile, DWORD dwPos)
{
DWORD length;
memset(pMemFile, 0, sizeof(*pMemFile));
pMemFile->end = WGetFileSize(hsFile, NULL);
length = 4096;
if (dwPos > length)
length = dwPos;
pMemFile->buf_len = length;
if (length >= pMemFile->end)
length = pMemFile->end;
pMemFile->buf_len = length;
pMemFile->buf = DiabloAllocPtr(length);
pMemFile->file = hsFile;
return pMemFile->buf;
}
void FreeMemFile(MEMFILE *pMemFile)
{
MemFreeDbg(pMemFile->buf);
}
BOOL ReadWaveFile(MEMFILE *pMemFile, WAVEFORMATEX *pwfx, CKINFO *chunk)
{
MMCKINFO hdr;
CKINFO fmt;
PCMWAVEFORMAT wf;
if (!ReadMemFile(pMemFile, &hdr, 12))
return FALSE;
if (hdr.ckid != FOURCC_RIFF || hdr.fccType != MAKEFOURCC('W', 'A', 'V', 'E'))
return FALSE;
if (!ReadWaveSection(pMemFile, MAKEFOURCC('f', 'm', 't', ' '), &fmt))
return FALSE;
if (fmt.dwSize < sizeof(PCMWAVEFORMAT))
return FALSE;
if (!ReadMemFile(pMemFile, &wf, sizeof(wf)))
return FALSE;
if (SeekMemFile(pMemFile, fmt.dwSize - sizeof(wf), FILE_CURRENT) == -1)
return FALSE;
pwfx->cbSize = 0;
pwfx->wFormatTag = wf.wf.wFormatTag;
pwfx->nChannels = wf.wf.nChannels;
pwfx->nSamplesPerSec = wf.wf.nSamplesPerSec;
pwfx->nAvgBytesPerSec = wf.wf.nAvgBytesPerSec;
pwfx->nBlockAlign = wf.wf.nBlockAlign;
pwfx->wBitsPerSample = wf.wBitsPerSample;
if (chunk == NULL)
return TRUE;
return ReadWaveSection(pMemFile, MAKEFOURCC('d', 'a', 't', 'a'), chunk);
}
BOOL ReadMemFile(MEMFILE *pMemFile, void *lpBuf, size_t length)
{
while (length) {
size_t to_copy;
if (!pMemFile->bytes_to_read)
FillMemFile(pMemFile);
to_copy = pMemFile->bytes_to_read;
if (length < to_copy)
to_copy = length;
if (!to_copy)
return FALSE;
memcpy(lpBuf, &pMemFile->buf[pMemFile->dist], to_copy);
pMemFile->offset += to_copy;
pMemFile->dist += to_copy;
pMemFile->bytes_to_read -= to_copy;
// BUGFIX: lpBuf is not incremented, next read will overwrite data
length -= to_copy;
}
return TRUE;
}
void FillMemFile(MEMFILE *pMemFile)
{
DWORD to_read;
WSetFilePointer(pMemFile->file, pMemFile->offset, NULL, FILE_BEGIN);
to_read = pMemFile->end - pMemFile->offset;
if (pMemFile->buf_len < to_read)
to_read = pMemFile->buf_len;
if (to_read)
WReadFile(pMemFile->file, pMemFile->buf, to_read);
pMemFile->dist = 0;
pMemFile->bytes_to_read = to_read;
}
int SeekMemFile(MEMFILE *pMemFile, ULONG lDist, DWORD dwMethod)
{
if (lDist < pMemFile->bytes_to_read) {
pMemFile->bytes_to_read -= lDist;
pMemFile->dist += lDist;
} else
pMemFile->bytes_to_read = 0;
pMemFile->offset += lDist;
return pMemFile->offset;
}
BOOL ReadWaveSection(MEMFILE *pMemFile, DWORD id, CKINFO *chunk)
{
DWORD hdr[2];
while (1) {
if (!ReadMemFile(pMemFile, hdr, sizeof(hdr)))
return FALSE;
if (hdr[0] == id)
break;
if (SeekMemFile(pMemFile, hdr[1], FILE_CURRENT) == -1)
return FALSE;
}
chunk->dwSize = hdr[1];
chunk->dwOffset = SeekMemFile(pMemFile, 0, FILE_CURRENT);
return chunk->dwOffset != (DWORD)-1;
}
BYTE *LoadWaveFile(HANDLE hsFile, WAVEFORMATEX *pwfx, CKINFO *chunk)
{
MEMFILE wave_file;
AllocateMemFile(hsFile, &wave_file, (DWORD)-1);
if (!ReadWaveFile(&wave_file, pwfx, chunk)) {
FreeMemFile(&wave_file);
return NULL;
}
return wave_file.buf;
}