dep: Bump libchdr to 54bfb87

This commit is contained in:
Stenzek 2023-08-12 13:41:50 +10:00
parent 0798292ee5
commit 4b70853daa
7 changed files with 660 additions and 199 deletions

View file

@ -1,6 +1,6 @@
/*
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_flac - v0.12.37 - 2022-02-12
dr_flac - v0.12.39 - 2022-09-17
David Reid - mackron@gmail.com
@ -210,6 +210,9 @@ Build Options
#define DR_FLAC_NO_SIMD
Disables SIMD optimizations (SSE on x86/x64 architectures, NEON on ARM architectures). Use this if you are having compatibility issues with your compiler.
#define DR_FLAC_NO_WCHAR
Disables all functions ending with `_w`. Use this if your compiler does not provide wchar.h. Not required if DR_FLAC_NO_STDIO is also defined.
Notes
@ -232,7 +235,7 @@ extern "C" {
#define DRFLAC_VERSION_MAJOR 0
#define DRFLAC_VERSION_MINOR 12
#define DRFLAC_VERSION_REVISION 37
#define DRFLAC_VERSION_REVISION 39
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
#include <stddef.h> /* For size_t. */
@ -383,15 +386,13 @@ typedef enum
drflac_seek_origin_current
} drflac_seek_origin;
/* Packing is important on this structure because we map this directly to the raw data within the SEEKTABLE metadata block. */
#pragma pack(2)
/* The order of members in this structure is important because we map this directly to the raw data within the SEEKTABLE metadata block. */
typedef struct
{
drflac_uint64 firstPCMFrame;
drflac_uint64 flacFrameOffset; /* The offset from the first byte of the header of the first frame. */
drflac_uint16 pcmFrameCount;
} drflac_seekpoint;
#pragma pack()
typedef struct
{
@ -1280,15 +1281,13 @@ typedef struct
const char* pRunningData;
} drflac_cuesheet_track_iterator;
/* Packing is important on this structure because we map this directly to the raw data within the CUESHEET metadata block. */
#pragma pack(4)
/* The order of members here is important because we map this directly to the raw data within the CUESHEET metadata block. */
typedef struct
{
drflac_uint64 offset;
drflac_uint8 index;
drflac_uint8 reserved[3];
} drflac_cuesheet_track_index;
#pragma pack()
typedef struct
{
@ -1363,9 +1362,15 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
I am using "__inline__" only when we're compiling in strict ANSI mode.
*/
#if defined(__STRICT_ANSI__)
#define DRFLAC_INLINE __inline__ __attribute__((always_inline))
#define DRFLAC_GNUC_INLINE_HINT __inline__
#else
#define DRFLAC_INLINE inline __attribute__((always_inline))
#define DRFLAC_GNUC_INLINE_HINT inline
#endif
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
#define DRFLAC_INLINE DRFLAC_GNUC_INLINE_HINT __attribute__((always_inline))
#else
#define DRFLAC_INLINE DRFLAC_GNUC_INLINE_HINT
#endif
#elif defined(__WATCOMC__)
#define DRFLAC_INLINE __inline
@ -1509,9 +1514,7 @@ static DRFLAC_INLINE drflac_bool32 drflac_has_sse41(void)
{
#if defined(DRFLAC_SUPPORT_SSE41)
#if (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(DRFLAC_NO_SSE41)
#if defined(DRFLAC_X64)
return DRFLAC_TRUE; /* 64-bit targets always support SSE4.1. */
#elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE4_1__)
#if defined(__SSE4_1__) || defined(__AVX__)
return DRFLAC_TRUE; /* If the compiler is allowed to freely generate SSE41 code we can assume support. */
#else
#if defined(DRFLAC_NO_CPUID)
@ -1576,18 +1579,21 @@ static DRFLAC_INLINE drflac_bool32 drflac_has_sse41(void)
extern __inline drflac_uint64 _watcom_bswap64(drflac_uint64);
#pragma aux _watcom_bswap16 = \
"xchg al, ah" \
parm [ax] \
modify [ax];
parm [ax] \
value [ax] \
modify nomemory;
#pragma aux _watcom_bswap32 = \
"bswap eax" \
parm [eax] \
modify [eax];
"bswap eax" \
parm [eax] \
value [eax] \
modify nomemory;
#pragma aux _watcom_bswap64 = \
"bswap eax" \
"bswap edx" \
"xchg eax,edx" \
parm [eax edx] \
modify [eax edx];
value [eax edx] \
modify nomemory;
#endif
@ -1688,6 +1694,10 @@ typedef drflac_int32 drflac_result;
#define DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE 9
#define DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE 10
#define DRFLAC_SEEKPOINT_SIZE_IN_BYTES 18
#define DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES 36
#define DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES 12
#define drflac_align(x, a) ((((x) + (a) - 1) / (a)) * (a))
@ -2690,6 +2700,10 @@ static drflac_bool32 drflac__find_and_seek_to_next_sync_code(drflac_bs* bs)
#if defined(__WATCOMC__) && defined(__386__)
#define DRFLAC_IMPLEMENT_CLZ_WATCOM
#endif
#ifdef __MRC__
#include <intrinsics.h>
#define DRFLAC_IMPLEMENT_CLZ_MRC
#endif
static DRFLAC_INLINE drflac_uint32 drflac__clz_software(drflac_cache_t x)
{
@ -2730,6 +2744,8 @@ static DRFLAC_INLINE drflac_bool32 drflac__is_lzcnt_supported(void)
/* Fast compile time check for ARM. */
#if defined(DRFLAC_HAS_LZCNT_INTRINSIC) && defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5)
return DRFLAC_TRUE;
#elif defined(__MRC__)
return DRFLAC_TRUE;
#else
/* If the compiler itself does not support the intrinsic then we'll need to return false. */
#ifdef DRFLAC_HAS_LZCNT_INTRINSIC
@ -2839,6 +2855,15 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_msvc(drflac_cache_t x)
#ifdef DRFLAC_IMPLEMENT_CLZ_WATCOM
static __inline drflac_uint32 drflac__clz_watcom (drflac_uint32);
#ifdef DRFLAC_IMPLEMENT_CLZ_WATCOM_LZCNT
/* Use the LZCNT instruction (only available on some processors since the 2010s). */
#pragma aux drflac__clz_watcom_lzcnt = \
"db 0F3h, 0Fh, 0BDh, 0C0h" /* lzcnt eax, eax */ \
parm [eax] \
value [eax] \
modify nomemory;
#else
/* Use the 386+-compatible implementation. */
#pragma aux drflac__clz_watcom = \
"bsr eax, eax" \
"xor eax, 31" \
@ -2846,6 +2871,7 @@ static __inline drflac_uint32 drflac__clz_watcom (drflac_uint32);
value [eax] \
modify exact [eax] nomemory;
#endif
#endif
static DRFLAC_INLINE drflac_uint32 drflac__clz(drflac_cache_t x)
{
@ -2857,8 +2883,12 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz(drflac_cache_t x)
{
#ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
return drflac__clz_msvc(x);
#elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM_LZCNT)
return drflac__clz_watcom_lzcnt(x);
#elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM)
return (x == 0) ? sizeof(x)*8 : drflac__clz_watcom(x);
#elif defined(__MRC__)
return __cntlzw(x);
#else
return drflac__clz_software(x);
#endif
@ -4420,7 +4450,7 @@ static drflac_bool32 drflac__decode_samples_with_residual__rice__neon_32(drflac_
const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
riceParamMask = ~((~0UL) << riceParam);
riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
riceParamMask128 = vdupq_n_u32(riceParamMask);
riceParam128 = vdupq_n_s32(riceParam);
@ -4606,10 +4636,13 @@ static drflac_bool32 drflac__decode_samples_with_residual__rice__neon_64(drflac_
int32x4_t riceParam128;
int64x1_t shift64;
uint32x4_t one128;
int64x2_t prediction128 = { 0 };
uint32x4_t zeroCountPart128;
uint32x4_t riceParamPart128;
const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
riceParamMask = ~((~0UL) << riceParam);
riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
riceParamMask128 = vdupq_n_u32(riceParamMask);
riceParam128 = vdupq_n_s32(riceParam);
@ -4686,10 +4719,6 @@ static drflac_bool32 drflac__decode_samples_with_residual__rice__neon_64(drflac_
/* For this version we are doing one sample at a time. */
while (pDecodedSamples < pDecodedSamplesEnd) {
int64x2_t prediction128 = vdupq_n_s64(0);
uint32x4_t zeroCountPart128;
uint32x4_t riceParamPart128;
if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0]) ||
!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[1], &riceParamParts[1]) ||
!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[2], &riceParamParts[2]) ||
@ -6437,7 +6466,7 @@ static void drflac__free_from_callbacks(void* p, const drflac_allocation_callbac
}
static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeektableSize, drflac_allocation_callbacks* pAllocationCallbacks)
static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeekpointCount, drflac_allocation_callbacks* pAllocationCallbacks)
{
/*
We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that
@ -6497,32 +6526,37 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
seektableSize = blockSize;
if (onMeta) {
drflac_uint32 seekpointCount;
drflac_uint32 iSeekpoint;
void* pRawData;
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
seekpointCount = blockSize/DRFLAC_SEEKPOINT_SIZE_IN_BYTES;
pRawData = drflac__malloc_from_callbacks(seekpointCount * sizeof(drflac_seekpoint), pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
metadata.data.seektable.seekpointCount = blockSize/sizeof(drflac_seekpoint);
metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
/* Endian swap. */
for (iSeekpoint = 0; iSeekpoint < metadata.data.seektable.seekpointCount; ++iSeekpoint) {
/* We need to read seekpoint by seekpoint and do some processing. */
for (iSeekpoint = 0; iSeekpoint < seekpointCount; ++iSeekpoint) {
drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint;
if (onRead(pUserData, pSeekpoint, DRFLAC_SEEKPOINT_SIZE_IN_BYTES) != DRFLAC_SEEKPOINT_SIZE_IN_BYTES) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
/* Endian swap. */
pSeekpoint->firstPCMFrame = drflac__be2host_64(pSeekpoint->firstPCMFrame);
pSeekpoint->flacFrameOffset = drflac__be2host_64(pSeekpoint->flacFrameOffset);
pSeekpoint->pcmFrameCount = drflac__be2host_16(pSeekpoint->pcmFrameCount);
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
metadata.data.seektable.seekpointCount = seekpointCount;
metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
@ -6607,9 +6641,15 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
void* pRawData;
const char* pRunningData;
const char* pRunningDataEnd;
size_t bufferSize;
drflac_uint8 iTrack;
drflac_uint8 iIndex;
void* pTrackData;
/*
This needs to be loaded in two passes. The first pass is used to calculate the size of the memory allocation
we need for storing the necessary data. The second pass will fill that buffer with usable data.
*/
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
@ -6630,38 +6670,91 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
metadata.data.cuesheet.leadInSampleCount = drflac__be2host_64(*(const drflac_uint64*)pRunningData); pRunningData += 8;
metadata.data.cuesheet.isCD = (pRunningData[0] & 0x80) != 0; pRunningData += 259;
metadata.data.cuesheet.trackCount = pRunningData[0]; pRunningData += 1;
metadata.data.cuesheet.pTrackData = pRunningData;
metadata.data.cuesheet.pTrackData = NULL; /* Will be filled later. */
/* Check that the cuesheet tracks are valid before passing it to the callback */
for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
drflac_uint8 indexCount;
drflac_uint32 indexPointSize;
/* Pass 1: Calculate the size of the buffer for the track data. */
{
const char* pRunningDataSaved = pRunningData; /* Will be restored at the end in preparation for the second pass. */
if (pRunningDataEnd - pRunningData < 36) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
bufferSize = metadata.data.cuesheet.trackCount * DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES;
for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
drflac_uint8 indexCount;
drflac_uint32 indexPointSize;
if (pRunningDataEnd - pRunningData < DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
/* Skip to the index point count */
pRunningData += 35;
indexCount = pRunningData[0];
pRunningData += 1;
bufferSize += indexCount * sizeof(drflac_cuesheet_track_index);
/* Quick validation check. */
indexPointSize = indexCount * DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES;
if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
pRunningData += indexPointSize;
}
/* Skip to the index point count */
pRunningData += 35;
indexCount = pRunningData[0]; pRunningData += 1;
indexPointSize = indexCount * sizeof(drflac_cuesheet_track_index);
if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
/* Endian swap. */
for (iIndex = 0; iIndex < indexCount; ++iIndex) {
drflac_cuesheet_track_index* pTrack = (drflac_cuesheet_track_index*)pRunningData;
pRunningData += sizeof(drflac_cuesheet_track_index);
pTrack->offset = drflac__be2host_64(pTrack->offset);
}
pRunningData = pRunningDataSaved;
}
/* Pass 2: Allocate a buffer and fill the data. Validation was done in the step above so can be skipped. */
{
char* pRunningTrackData;
pTrackData = drflac__malloc_from_callbacks(bufferSize, pAllocationCallbacks);
if (pTrackData == NULL) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
pRunningTrackData = (char*)pTrackData;
for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
drflac_uint8 indexCount;
DRFLAC_COPY_MEMORY(pRunningTrackData, pRunningData, DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES);
pRunningData += DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES-1; /* Skip forward, but not beyond the last byte in the CUESHEET_TRACK block which is the index count. */
pRunningTrackData += DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES-1;
/* Grab the index count for the next part. */
indexCount = pRunningData[0];
pRunningData += 1;
pRunningTrackData += 1;
/* Extract each track index. */
for (iIndex = 0; iIndex < indexCount; ++iIndex) {
drflac_cuesheet_track_index* pTrackIndex = (drflac_cuesheet_track_index*)pRunningTrackData;
DRFLAC_COPY_MEMORY(pRunningTrackData, pRunningData, DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES);
pRunningData += DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES;
pRunningTrackData += sizeof(drflac_cuesheet_track_index);
pTrackIndex->offset = drflac__be2host_64(pTrackIndex->offset);
}
}
metadata.data.cuesheet.pTrackData = pTrackData;
}
/* The original data is no longer needed. */
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
pRawData = NULL;
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
drflac__free_from_callbacks(pTrackData, pAllocationCallbacks);
pTrackData = NULL;
}
} break;
@ -6700,7 +6793,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
metadata.data.picture.descriptionLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
/* Need space for the rest of the block */
@ -6708,7 +6801,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
metadata.data.picture.width = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.height = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.colorDepth = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
@ -6791,9 +6884,9 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
}
}
*pSeektablePos = seektablePos;
*pSeektableSize = seektableSize;
*pFirstFramePos = runningFilePos;
*pSeektablePos = seektablePos;
*pSeekpointCount = seektableSize / DRFLAC_SEEKPOINT_SIZE_IN_BYTES;
*pFirstFramePos = runningFilePos;
return DRFLAC_TRUE;
}
@ -7823,11 +7916,11 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
drflac_uint32 wholeSIMDVectorCountPerChannel;
drflac_uint32 decodedSamplesAllocationSize;
#ifndef DR_FLAC_NO_OGG
drflac_oggbs oggbs;
drflac_oggbs* pOggbs = NULL;
#endif
drflac_uint64 firstFramePos;
drflac_uint64 seektablePos;
drflac_uint32 seektableSize;
drflac_uint32 seekpointCount;
drflac_allocation_callbacks allocationCallbacks;
drflac* pFlac;
@ -7881,18 +7974,21 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
/* There's additional data required for Ogg streams. */
if (init.container == drflac_container_ogg) {
allocationSize += sizeof(drflac_oggbs);
}
DRFLAC_ZERO_MEMORY(&oggbs, sizeof(oggbs));
if (init.container == drflac_container_ogg) {
oggbs.onRead = onRead;
oggbs.onSeek = onSeek;
oggbs.pUserData = pUserData;
oggbs.currentBytePos = init.oggFirstBytePos;
oggbs.firstBytePos = init.oggFirstBytePos;
oggbs.serialNumber = init.oggSerial;
oggbs.bosPageHeader = init.oggBosHeader;
oggbs.bytesRemainingInPage = 0;
pOggbs = (drflac_oggbs*)drflac__malloc_from_callbacks(sizeof(*pOggbs), &allocationCallbacks);
if (pOggbs == NULL) {
return NULL; /*DRFLAC_OUT_OF_MEMORY;*/
}
DRFLAC_ZERO_MEMORY(pOggbs, sizeof(*pOggbs));
pOggbs->onRead = onRead;
pOggbs->onSeek = onSeek;
pOggbs->pUserData = pUserData;
pOggbs->currentBytePos = init.oggFirstBytePos;
pOggbs->firstBytePos = init.oggFirstBytePos;
pOggbs->serialNumber = init.oggSerial;
pOggbs->bosPageHeader = init.oggBosHeader;
pOggbs->bytesRemainingInPage = 0;
}
#endif
@ -7901,9 +7997,9 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
consist of only a single heap allocation. To this, the size of the seek table needs to be known, which we determine when reading
and decoding the metadata.
*/
firstFramePos = 42; /* <-- We know we are at byte 42 at this point. */
seektablePos = 0;
seektableSize = 0;
firstFramePos = 42; /* <-- We know we are at byte 42 at this point. */
seektablePos = 0;
seekpointCount = 0;
if (init.hasMetadataBlocks) {
drflac_read_proc onReadOverride = onRead;
drflac_seek_proc onSeekOverride = onSeek;
@ -7913,20 +8009,26 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
if (init.container == drflac_container_ogg) {
onReadOverride = drflac__on_read_ogg;
onSeekOverride = drflac__on_seek_ogg;
pUserDataOverride = (void*)&oggbs;
pUserDataOverride = (void*)pOggbs;
}
#endif
if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seektableSize, &allocationCallbacks)) {
if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
#ifndef DR_FLAC_NO_OGG
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
#endif
return NULL;
}
allocationSize += seektableSize;
allocationSize += seekpointCount * sizeof(drflac_seekpoint);
}
pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
if (pFlac == NULL) {
#ifndef DR_FLAC_NO_OGG
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
#endif
return NULL;
}
@ -7936,8 +8038,12 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
#ifndef DR_FLAC_NO_OGG
if (init.container == drflac_container_ogg) {
drflac_oggbs* pInternalOggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize + seektableSize);
*pInternalOggbs = oggbs;
drflac_oggbs* pInternalOggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize + (seekpointCount * sizeof(drflac_seekpoint)));
DRFLAC_COPY_MEMORY(pInternalOggbs, pOggbs, sizeof(*pOggbs));
/* At this point the pOggbs object has been handed over to pInternalOggbs and can be freed. */
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
pOggbs = NULL;
/* The Ogg bistream needs to be layered on top of the original bitstream. */
pFlac->bs.onRead = drflac__on_read_ogg;
@ -7961,7 +8067,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
{
/* If we have a seektable we need to load it now, making sure we move back to where we were previously. */
if (seektablePos != 0) {
pFlac->seekpointCount = seektableSize / sizeof(*pFlac->pSeekpoints);
pFlac->seekpointCount = seekpointCount;
pFlac->pSeekpoints = (drflac_seekpoint*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize);
DRFLAC_ASSERT(pFlac->bs.onSeek != NULL);
@ -7969,18 +8075,20 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
/* Seek to the seektable, then just read directly into our seektable buffer. */
if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) {
if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints, seektableSize) == seektableSize) {
/* Endian swap. */
drflac_uint32 iSeekpoint;
for (iSeekpoint = 0; iSeekpoint < pFlac->seekpointCount; ++iSeekpoint) {
drflac_uint32 iSeekpoint;
for (iSeekpoint = 0; iSeekpoint < seekpointCount; iSeekpoint += 1) {
if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints + iSeekpoint, DRFLAC_SEEKPOINT_SIZE_IN_BYTES) == DRFLAC_SEEKPOINT_SIZE_IN_BYTES) {
/* Endian swap. */
pFlac->pSeekpoints[iSeekpoint].firstPCMFrame = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].firstPCMFrame);
pFlac->pSeekpoints[iSeekpoint].flacFrameOffset = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].flacFrameOffset);
pFlac->pSeekpoints[iSeekpoint].pcmFrameCount = drflac__be2host_16(pFlac->pSeekpoints[iSeekpoint].pcmFrameCount);
} else {
/* Failed to read the seektable. Pretend we don't have one. */
pFlac->pSeekpoints = NULL;
pFlac->seekpointCount = 0;
break;
}
} else {
/* Failed to read the seektable. Pretend we don't have one. */
pFlac->pSeekpoints = NULL;
pFlac->seekpointCount = 0;
}
/* We need to seek back to where we were. If this fails it's a critical error. */
@ -8029,7 +8137,9 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
#ifndef DR_FLAC_NO_STDIO
#include <stdio.h>
#ifndef DR_FLAC_NO_WCHAR
#include <wchar.h> /* For wcslen(), wcsrtombs() */
#endif
/* drflac_result_from_errno() is only used for fopen() and wfopen() so putting it inside DR_WAV_NO_STDIO for now. If something else needs this later we can move it out. */
#include <errno.h>
@ -8495,6 +8605,7 @@ fallback, so if you notice your compiler not detecting this properly I'm happy t
#endif
#endif
#ifndef DR_FLAC_NO_WCHAR
static drflac_result drflac_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (ppFile != NULL) {
@ -8523,10 +8634,23 @@ static drflac_result drflac_wfopen(FILE** ppFile, const wchar_t* pFilePath, cons
}
#else
/*
Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
Use fopen() on anything other than Windows. Requires a conversion. This is annoying because
fopen() is locale specific. The only real way I can think of to do this is with wcsrtombs(). Note
that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler
error I'll look into improving compatibility.
*/
/*
Some compilers don't support wchar_t or wcsrtombs() which we're using below. In this case we just
need to abort with an error. If you encounter a compiler lacking such support, add it to this list
and submit a bug report and it'll be added to the library upstream.
*/
#if defined(__DJGPP__)
{
/* Nothing to do here. This will fall through to the error check below. */
}
#else
{
mbstate_t mbs;
size_t lenMB;
@ -8568,6 +8692,7 @@ static drflac_result drflac_wfopen(FILE** ppFile, const wchar_t* pFilePath, cons
drflac__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
}
#endif
if (*ppFile == NULL) {
return DRFLAC_ERROR;
@ -8576,6 +8701,7 @@ static drflac_result drflac_wfopen(FILE** ppFile, const wchar_t* pFilePath, cons
return DRFLAC_SUCCESS;
}
#endif
static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
{
@ -8608,6 +8734,7 @@ DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocati
return pFlac;
}
#ifndef DR_FLAC_NO_WCHAR
DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
@ -8625,6 +8752,7 @@ DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_all
return pFlac;
}
#endif
DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
{
@ -8644,6 +8772,7 @@ DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_
return pFlac;
}
#ifndef DR_FLAC_NO_WCHAR
DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
@ -8661,6 +8790,7 @@ DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, dr
return pFlac;
}
#endif
#endif /* DR_FLAC_NO_STDIO */
static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t bytesToRead)
@ -11928,6 +12058,18 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
/*
REVISION HISTORY
================
v0.12.39 - 2022-09-17
- Fix compilation with DJGPP.
- Fix compilation error with Visual Studio 2019 and the ARM build.
- Fix an error with SSE 4.1 detection.
- Add support for disabling wchar_t with DR_WAV_NO_WCHAR.
- Improve compatibility with compilers which lack support for explicit struct packing.
- Improve compatibility with low-end and embedded hardware by reducing the amount of stack
allocation when loading an Ogg encapsulated file.
v0.12.38 - 2022-04-10
- Fix compilation error on older versions of GCC.
v0.12.37 - 2022-02-12
- Improve ARM detection.

View file

@ -204,6 +204,9 @@ extern "C" {
#define CHD_CODEC_NONE 0
#define CHD_CODEC_ZLIB CHD_MAKE_TAG('z','l','i','b')
#define CHD_CODEC_LZMA CHD_MAKE_TAG('l','z','m','a')
#define CHD_CODEC_HUFFMAN CHD_MAKE_TAG('h','u','f','f')
#define CHD_CODEC_FLAC CHD_MAKE_TAG('f','l','a','c')
/* general codecs with CD frontend */
#define CHD_CODEC_CD_ZLIB CHD_MAKE_TAG('c','d','z','l')
#define CHD_CODEC_CD_LZMA CHD_MAKE_TAG('c','d','l','z')
@ -370,12 +373,12 @@ struct _chd_verify_result
/* chd_error chd_create_file(core_file *file, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent); */
/* open an existing CHD file */
CHD_EXPORT chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd);
CHD_EXPORT chd_error chd_open_core_file(core_file *file, int mode, chd_file *parent, chd_file **chd);
CHD_EXPORT chd_error chd_open_file(FILE *file, int mode, chd_file *parent, chd_file **chd);
CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd);
/* precache underlying file */
CHD_EXPORT chd_error chd_precache(chd_file *chd);
CHD_EXPORT chd_error chd_precache_progress(chd_file* chd, void(*progress)(size_t pos, size_t total, void* param), void* param);
/* close a CHD file */
CHD_EXPORT void chd_close(chd_file *chd);

View file

@ -4,8 +4,21 @@
#include <stdint.h>
#include <stdio.h>
#ifdef USE_LIBRETRO_VFS
#include <streams/file_stream_transforms.h>
#endif
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
#if defined(__PS3__) || defined(__PSL1GHT__)
#undef UINT32
#undef UINT16
#undef UINT8
#undef INT32
#undef INT16
#undef INT8
#endif
typedef uint64_t UINT64;
typedef uint32_t UINT32;
typedef uint16_t UINT16;
@ -16,33 +29,50 @@ typedef int32_t INT32;
typedef int16_t INT16;
typedef int8_t INT8;
#define core_file FILE
#define core_fopen(file) fopen(file, "rb")
typedef struct chd_core_file {
/*
* arbitrary pointer to data the implementation uses to implement the below functions
*/
void *argp;
#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WIN64__)
#define core_fseek _fseeki64
#define core_ftell _ftelli64
#elif defined(_LARGEFILE_SOURCE) && defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
#define core_fseek fseeko64
#define core_ftell ftello64
#elif defined(__PS3__) && !defined(__PSL1GHT__) || defined(__SWITCH__)
#define core_fseek(x,y,z) fseek(x,(off_t)y,z)
#define core_ftell(x) (off_t)ftell(x)
#else
#define core_fseek fseeko
#define core_ftell ftello
#endif
#define core_fread(fc, buff, len) fread(buff, 1, len, fc)
#define core_fclose fclose
/*
* return the size of a given file as a 64-bit unsigned integer.
* the position of the file pointer after calling this function is
* undefined because many implementations will seek to the end of the
* file and call ftell.
*
* on error, (UINT64)-1 is returned.
*/
UINT64(*fsize)(struct chd_core_file*);
static inline UINT64 core_fsize(core_file *f)
/*
* should match the behavior of fread, except the FILE* argument at the end
* will be replaced with a struct chd_core_file*.
*/
size_t(*fread)(void*,size_t,size_t,struct chd_core_file*);
// closes the given file.
int (*fclose)(struct chd_core_file*);
// fseek clone
int (*fseek)(struct chd_core_file*, INT64, int);
} core_file;
static inline int core_fclose(core_file *fp) {
return fp->fclose(fp);
}
static inline size_t core_fread(core_file *fp, void *ptr, size_t len) {
return fp->fread(ptr, 1, len, fp);
}
static inline int core_fseek(core_file* fp, INT64 offset, int whence) {
return fp->fseek(fp, offset, whence);
}
static inline UINT64 core_fsize(core_file *fp)
{
UINT64 rv;
UINT64 p = core_ftell(f);
core_fseek(f, 0, SEEK_END);
rv = core_ftell(f);
core_fseek(f, p, SEEK_SET);
return rv;
return fp->fsize(fp);
}
#endif

View file

@ -227,6 +227,12 @@ struct _lzma_codec_data
lzma_allocator allocator;
};
typedef struct _huff_codec_data huff_codec_data;
struct _huff_codec_data
{
struct huffman_decoder* decoder;
};
/* codec-private data for the CDZL codec */
typedef struct _cdzl_codec_data cdzl_codec_data;
struct _cdzl_codec_data {
@ -249,6 +255,14 @@ struct _cdlz_codec_data {
uint8_t* buffer;
};
/* codec-private data for the FLAC codec */
typedef struct _flac_codec_data flac_codec_data;
struct _flac_codec_data {
/* internal state */
int native_endian;
flac_decoder decoder;
};
/* codec-private data for the CDFL codec */
typedef struct _cdfl_codec_data cdfl_codec_data;
struct _cdfl_codec_data {
@ -267,7 +281,6 @@ struct _chd_file
UINT32 cookie; /* cookie, should equal COOKIE_VALUE */
core_file * file; /* handle to the open core file */
UINT8 owns_file; /* flag indicating if this file should be closed on chd_close() */
chd_header header; /* header, extracted from file */
chd_file * parent; /* pointer to parent file, or NULL */
@ -286,6 +299,9 @@ struct _chd_file
const codec_interface * codecintf[4]; /* interface to the codec */
zlib_codec_data zlib_codec_data; /* zlib codec data */
lzma_codec_data lzma_codec_data; /* lzma codec data */
huff_codec_data huff_codec_data; /* huff codec data */
flac_codec_data flac_codec_data; /* flac codec data */
cdzl_codec_data cdzl_codec_data; /* cdzl codec data */
cdlz_codec_data cdlz_codec_data; /* cdlz codec data */
cdfl_codec_data cdfl_codec_data; /* cdfl codec data */
@ -309,6 +325,14 @@ static const UINT8 nullsha1[CHD_SHA1_BYTES] = { 0 };
PROTOTYPES
***************************************************************************/
/* core_file wrappers over stdio */
static core_file *core_stdio_fopen(char const *path);
static UINT64 core_stdio_fsize(core_file *file);
static size_t core_stdio_fread(void *ptr, size_t size, size_t nmemb, core_file *file);
static int core_stdio_fclose(core_file *file);
static int core_stdio_fclose_nonowner(core_file *file); // alternate fclose used by chd_open_file
static int core_stdio_fseek(core_file* file, INT64 offset, int whence);
/* internal header operations */
static chd_error header_validate(const chd_header *header);
static chd_error header_read(chd_file *chd, chd_header *header);
@ -338,6 +362,16 @@ static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes);
static void lzma_codec_free(void *codec);
static chd_error lzma_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
/* huff compression codec */
static chd_error huff_codec_init(void *codec, uint32_t hunkbytes);
static void huff_codec_free(void *codec);
static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
/* flac compression codec */
static chd_error flac_codec_init(void *codec, uint32_t hunkbytes);
static void flac_codec_free(void *codec);
static chd_error flac_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
/* cdzl compression codec */
static chd_error cdzl_codec_init(void* codec, uint32_t hunkbytes);
static void cdzl_codec_free(void* codec);
@ -749,24 +783,121 @@ static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t
return CHDERR_NONE;
}
/***************************************************************************
* HUFFMAN DECOMPRESSOR
***************************************************************************
*/
static chd_error huff_codec_init(void* codec, uint32_t hunkbytes)
{
huff_codec_data* huff_codec = (huff_codec_data*) codec;
huff_codec->decoder = create_huffman_decoder(256, 16);
return CHDERR_NONE;
}
static void huff_codec_free(void *codec)
{
huff_codec_data* huff_codec = (huff_codec_data*) codec;
delete_huffman_decoder(huff_codec->decoder);
}
static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
huff_codec_data* huff_codec = (huff_codec_data*) codec;
struct bitstream* bitbuf = create_bitstream(src, complen);
// first import the tree
enum huffman_error err = huffman_import_tree_huffman(huff_codec->decoder, bitbuf);
if (err != HUFFERR_NONE)
{
free(bitbuf);
return err;
}
// then decode the data
for (uint32_t cur = 0; cur < destlen; cur++)
dest[cur] = huffman_decode_one(huff_codec->decoder, bitbuf);
bitstream_flush(bitbuf);
chd_error result = bitstream_overflow(bitbuf) ? CHDERR_DECOMPRESSION_ERROR : CHDERR_NONE;
free(bitbuf);
return result;
}
/***************************************************************************
* CD FLAC DECOMPRESSOR
***************************************************************************
*/
/*------------------------------------------------------
* cdfl_codec_blocksize - return the optimal block size
* flac_codec_blocksize - return the optimal block size
*------------------------------------------------------
*/
static uint32_t cdfl_codec_blocksize(uint32_t bytes)
static uint32_t flac_codec_blocksize(uint32_t bytes)
{
/* determine FLAC block size, which must be 16-65535
* clamp to 2k since that's supposed to be the sweet spot */
uint32_t hunkbytes = bytes / 4;
while (hunkbytes > 2048)
hunkbytes /= 2;
return hunkbytes;
uint32_t blocksize = bytes / 4;
while (blocksize > 2048)
blocksize /= 2;
return blocksize;
}
static chd_error flac_codec_init(void *codec, uint32_t hunkbytes)
{
uint16_t native_endian = 0;
flac_codec_data *flac = (flac_codec_data*)codec;
/* make sure the CHD's hunk size is an even multiple of the sample size */
if (hunkbytes % 4 != 0)
return CHDERR_CODEC_ERROR;
/* determine whether we want native or swapped samples */
*(uint8_t *)(&native_endian) = 1;
flac->native_endian = (native_endian & 1);
/* flac decoder init */
if (flac_decoder_init(&flac->decoder))
return CHDERR_OUT_OF_MEMORY;
return CHDERR_NONE;
}
static void flac_codec_free(void *codec)
{
flac_codec_data *flac = (flac_codec_data*)codec;
flac_decoder_free(&flac->decoder);
}
static chd_error flac_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
flac_codec_data *flac = (flac_codec_data*)codec;
int swap_endian;
if (src[0] == 'L')
swap_endian = !flac->native_endian;
else if (src[0] == 'B')
swap_endian = flac->native_endian;
else
return CHDERR_DECOMPRESSION_ERROR;
if (!flac_decoder_reset(&flac->decoder, 44100, 2, flac_codec_blocksize(destlen), src + 1, complen - 1))
return CHDERR_DECOMPRESSION_ERROR;
if (!flac_decoder_decode_interleaved(&flac->decoder, (int16_t *)(dest), destlen/4, swap_endian))
return CHDERR_DECOMPRESSION_ERROR;
flac_decoder_finish(&flac->decoder);
return CHDERR_NONE;
}
static uint32_t cdfl_codec_blocksize(uint32_t bytes)
{
// for CDs it seems that CD_MAX_SECTOR_DATA is the right target
uint32_t blocksize = bytes / 4;
while (blocksize > CD_MAX_SECTOR_DATA)
blocksize /= 2;
return blocksize;
}
static chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
@ -904,6 +1035,39 @@ static const codec_interface codec_interfaces[] =
NULL
},
/* V5 lzma compression */
{
CHD_CODEC_LZMA,
"lzma (LZMA)",
FALSE,
lzma_codec_init,
lzma_codec_free,
lzma_codec_decompress,
NULL
},
/* V5 huffman compression */
{
CHD_CODEC_HUFFMAN,
"Huffman",
FALSE,
huff_codec_init,
huff_codec_free,
huff_codec_decompress,
NULL
},
/* V5 flac compression */
{
CHD_CODEC_FLAC,
"flac (FLAC)",
FALSE,
flac_codec_init,
flac_codec_free,
flac_codec_decompress,
NULL
},
/* V5 CD zlib compression */
{
CHD_CODEC_CD_ZLIB,
@ -1185,6 +1349,8 @@ static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
if (!chd_compressed(header))
{
header->rawmap = (uint8_t*)malloc(rawmapsize);
if (header->rawmap == NULL)
return CHDERR_OUT_OF_MEMORY;
core_fseek(chd->file, header->mapoffset, SEEK_SET);
result = core_fread(chd->file, header->rawmap, rawmapsize);
return CHDERR_NONE;
@ -1202,10 +1368,18 @@ static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
/* now read the map */
compressed_ptr = (uint8_t*)malloc(sizeof(uint8_t) * mapbytes);
if (compressed_ptr == NULL)
return CHDERR_OUT_OF_MEMORY;
core_fseek(chd->file, header->mapoffset + 16, SEEK_SET);
result = core_fread(chd->file, compressed_ptr, mapbytes);
bitbuf = create_bitstream(compressed_ptr, sizeof(uint8_t) * mapbytes);
header->rawmap = (uint8_t*)malloc(rawmapsize);
if (header->rawmap == NULL)
{
free(compressed_ptr);
free(bitbuf);
return CHDERR_OUT_OF_MEMORY;
}
/* first decode the compression types */
decoder = create_huffman_decoder(16, 8);
@ -1343,7 +1517,24 @@ static inline void map_extract_old(const UINT8 *base, map_entry *entry, UINT32 h
chd_open_file - open a CHD file for access
-------------------------------------------------*/
CHD_EXPORT chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd)
CHD_EXPORT chd_error chd_open_file(FILE *file, int mode, chd_file *parent, chd_file **chd) {
core_file *stream = malloc(sizeof(core_file));
if (!stream)
return CHDERR_OUT_OF_MEMORY;
stream->argp = file;
stream->fsize = core_stdio_fsize;
stream->fread = core_stdio_fread;
stream->fclose = core_stdio_fclose_nonowner;
stream->fseek = core_stdio_fseek;
return chd_open_core_file(stream, mode, parent, chd);
}
/*-------------------------------------------------
chd_open_core_file - open a CHD file for access
-------------------------------------------------*/
CHD_EXPORT chd_error chd_open_core_file(core_file *file, int mode, chd_file *parent, chd_file **chd)
{
chd_file *newchd = NULL;
chd_error err;
@ -1492,6 +1683,18 @@ CHD_EXPORT chd_error chd_open_file(core_file *file, int mode, chd_file *parent,
codec = &newchd->zlib_codec_data;
break;
case CHD_CODEC_LZMA:
codec = &newchd->lzma_codec_data;
break;
case CHD_CODEC_HUFFMAN:
codec = &newchd->huff_codec_data;
break;
case CHD_CODEC_FLAC:
codec = &newchd->flac_codec_data;
break;
case CHD_CODEC_CD_ZLIB:
codec = &newchd->cdzl_codec_data;
break;
@ -1530,56 +1733,26 @@ cleanup:
memory
-------------------------------------------------*/
CHD_EXPORT chd_error chd_precache(chd_file* chd)
CHD_EXPORT chd_error chd_precache(chd_file *chd)
{
return chd_precache_progress(chd, NULL, NULL);
}
CHD_EXPORT chd_error chd_precache_progress(chd_file *chd, void(*progress)(size_t pos, size_t total, void* param), void* param)
{
#define PRECACHE_CHUNK_SIZE 16 * 1024 * 1024
#ifdef _MSC_VER
size_t size, done, req_count, count, last_update_done, update_interval;
#else
ssize_t size, done, req_count, count, last_update_done, update_interval;
#endif
INT64 count;
UINT64 size;
if (chd->file_cache == NULL)
{
core_fseek(chd->file, 0, SEEK_END);
size = core_ftell(chd->file);
if (size <= 0)
size = core_fsize(chd->file);
if ((INT64)size <= 0)
return CHDERR_INVALID_DATA;
chd->file_cache = malloc(size);
if (chd->file_cache == NULL)
return CHDERR_OUT_OF_MEMORY;
core_fseek(chd->file, 0, SEEK_SET);
done = 0;
last_update_done = 0;
update_interval = ((size + 99) / 100);
while (done < size)
count = core_fread(chd->file, chd->file_cache, size);
if (count != size)
{
req_count = size - done;
if (req_count > PRECACHE_CHUNK_SIZE)
req_count = PRECACHE_CHUNK_SIZE;
count = core_fread(chd->file, chd->file_cache + done, req_count);
if (count != req_count)
{
free(chd->file_cache);
chd->file_cache = NULL;
return CHDERR_READ_ERROR;
}
done += req_count;
if (progress != NULL && (done - last_update_done) >= update_interval && done != size)
{
last_update_done = done;
progress(done, size, param);
}
free(chd->file_cache);
chd->file_cache = NULL;
return CHDERR_READ_ERROR;
}
}
@ -1614,7 +1787,7 @@ CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent,
}
/* open the file */
file = core_fopen(filename);
file = core_stdio_fopen(filename);
if (file == 0)
{
err = CHDERR_FILE_NOT_FOUND;
@ -1622,12 +1795,7 @@ CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent,
}
/* now open the CHD */
err = chd_open_file(file, mode, parent, chd);
if (err != CHDERR_NONE)
goto cleanup;
/* we now own this file */
(*chd)->owns_file = TRUE;
return chd_open_core_file(file, mode, parent, chd);
cleanup:
if ((err != CHDERR_NONE) && (file != NULL))
@ -1664,18 +1832,30 @@ CHD_EXPORT void chd_close(chd_file *chd)
switch (chd->codecintf[i]->compression)
{
case CHD_CODEC_CD_LZMA:
codec = &chd->cdlz_codec_data;
break;
case CHD_CODEC_ZLIB:
codec = &chd->zlib_codec_data;
break;
case CHD_CODEC_LZMA:
codec = &chd->lzma_codec_data;
break;
case CHD_CODEC_HUFFMAN:
codec = &chd->huff_codec_data;
break;
case CHD_CODEC_FLAC:
codec = &chd->flac_codec_data;
break;
case CHD_CODEC_CD_ZLIB:
codec = &chd->cdzl_codec_data;
break;
case CHD_CODEC_CD_LZMA:
codec = &chd->cdlz_codec_data;
break;
case CHD_CODEC_CD_FLAC:
codec = &chd->cdfl_codec_data;
break;
@ -1709,7 +1889,7 @@ CHD_EXPORT void chd_close(chd_file *chd)
free(chd->map);
/* close the file */
if (chd->owns_file && chd->file != NULL)
if (chd->file != NULL)
core_fclose(chd->file);
#ifdef NEED_CACHE_HUNK
@ -1808,7 +1988,7 @@ CHD_EXPORT chd_error chd_read_header(const char *filename, chd_header *header)
EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
/* open the file */
chd.file = core_fopen(filename);
chd.file = core_stdio_fopen(filename);
if (chd.file == NULL)
EARLY_EXIT(err = CHDERR_FILE_NOT_FOUND);
@ -2096,6 +2276,8 @@ static chd_error header_read(chd_file *chd, chd_header *header)
header->logicalbytes = (UINT64)header->obsolete_cylinders * (UINT64)header->obsolete_heads * (UINT64)header->obsolete_sectors * (UINT64)seclen;
header->hunkbytes = seclen * header->obsolete_hunksize;
header->unitbytes = header_guess_unitbytes(chd);
if (header->unitbytes == 0)
return CHDERR_INVALID_DATA;
header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
header->metaoffset = 0;
}
@ -2110,6 +2292,8 @@ static chd_error header_read(chd_file *chd, chd_header *header)
memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
header->hunkbytes = get_bigendian_uint32(&rawheader[76]);
header->unitbytes = header_guess_unitbytes(chd);
if (header->unitbytes == 0)
return CHDERR_INVALID_DATA;
header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
memcpy(header->sha1, &rawheader[80], CHD_SHA1_BYTES);
memcpy(header->parentsha1, &rawheader[100], CHD_SHA1_BYTES);
@ -2123,6 +2307,8 @@ static chd_error header_read(chd_file *chd, chd_header *header)
header->metaoffset = get_bigendian_uint64(&rawheader[36]);
header->hunkbytes = get_bigendian_uint32(&rawheader[44]);
header->unitbytes = header_guess_unitbytes(chd);
if (header->unitbytes == 0)
return CHDERR_INVALID_DATA;
header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
memcpy(header->sha1, &rawheader[48], CHD_SHA1_BYTES);
memcpy(header->parentsha1, &rawheader[68], CHD_SHA1_BYTES);
@ -2141,8 +2327,12 @@ static chd_error header_read(chd_file *chd, chd_header *header)
header->mapoffset = get_bigendian_uint64(&rawheader[40]);
header->metaoffset = get_bigendian_uint64(&rawheader[48]);
header->hunkbytes = get_bigendian_uint32(&rawheader[56]);
if (header->hunkbytes == 0)
return CHDERR_INVALID_DATA;
header->hunkcount = (header->logicalbytes + header->hunkbytes - 1) / header->hunkbytes;
header->unitbytes = get_bigendian_uint32(&rawheader[60]);
if (header->unitbytes == 0)
return CHDERR_INVALID_DATA;
header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
memcpy(header->sha1, &rawheader[84], CHD_SHA1_BYTES);
memcpy(header->parentsha1, &rawheader[104], CHD_SHA1_BYTES);
@ -2382,18 +2572,30 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
return CHDERR_READ_ERROR;
switch (chd->codecintf[rawmap[0]]->compression)
{
case CHD_CODEC_CD_LZMA:
codec = &chd->cdlz_codec_data;
break;
case CHD_CODEC_ZLIB:
codec = &chd->zlib_codec_data;
break;
case CHD_CODEC_LZMA:
codec = &chd->lzma_codec_data;
break;
case CHD_CODEC_HUFFMAN:
codec = &chd->huff_codec_data;
break;
case CHD_CODEC_FLAC:
codec = &chd->flac_codec_data;
break;
case CHD_CODEC_CD_ZLIB:
codec = &chd->cdzl_codec_data;
break;
case CHD_CODEC_CD_LZMA:
codec = &chd->cdlz_codec_data;
break;
case CHD_CODEC_CD_FLAC:
codec = &chd->cdfl_codec_data;
break;
@ -2625,10 +2827,6 @@ static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
else
err = CHDERR_NONE;
/* handle an error */
if (err != CHDERR_NONE)
free(data);
return err;
}
@ -2768,3 +2966,87 @@ static void zlib_allocator_free(voidpf opaque)
if (alloc->allocptr[i])
free(alloc->allocptr[i]);
}
/*-------------------------------------------------
core_stdio_fopen - core_file wrapper over fopen
-------------------------------------------------*/
static core_file *core_stdio_fopen(char const *path) {
core_file *file = malloc(sizeof(core_file));
if (!file)
return NULL;
if (!(file->argp = fopen(path, "rb"))) {
free(file);
return NULL;
}
file->fsize = core_stdio_fsize;
file->fread = core_stdio_fread;
file->fclose = core_stdio_fclose;
file->fseek = core_stdio_fseek;
return file;
}
/*-------------------------------------------------
core_stdio_fsize - core_file function for
getting file size with stdio
-------------------------------------------------*/
static UINT64 core_stdio_fsize(core_file *file) {
#if defined USE_LIBRETRO_VFS
#define core_stdio_fseek_impl fseek
#define core_stdio_ftell_impl ftell
#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WIN64__)
#define core_stdio_fseek_impl _fseeki64
#define core_stdio_ftell_impl _ftelli64
#elif defined(_LARGEFILE_SOURCE) && defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
#define core_stdio_fseek_impl fseeko64
#define core_stdio_ftell_impl ftello64
#elif defined(__PS3__) && !defined(__PSL1GHT__) || defined(__SWITCH__) || defined(__vita__)
#define core_stdio_fseek_impl(x,y,z) fseek(x,(off_t)y,z)
#define core_stdio_ftell_impl(x) (off_t)ftell(x)
#else
#define core_stdio_fseek_impl fseeko
#define core_stdio_ftell_impl ftello
#endif
FILE *fp;
UINT64 p, rv;
fp = (FILE*)file->argp;
p = core_stdio_ftell_impl(fp);
core_stdio_fseek_impl(fp, 0, SEEK_END);
rv = core_stdio_ftell_impl(fp);
core_stdio_fseek_impl(fp, p, SEEK_SET);
return rv;
}
/*-------------------------------------------------
core_stdio_fread - core_file wrapper over fread
-------------------------------------------------*/
static size_t core_stdio_fread(void *ptr, size_t size, size_t nmemb, core_file *file) {
return fread(ptr, size, nmemb, (FILE*)file->argp);
}
/*-------------------------------------------------
core_stdio_fclose - core_file wrapper over fclose
-------------------------------------------------*/
static int core_stdio_fclose(core_file *file) {
int err = fclose((FILE*)file->argp);
if (err == 0)
free(file);
return err;
}
/*-------------------------------------------------
core_stdio_fclose_nonowner - don't call fclose because
we don't own the underlying file, but do free the
core_file because libchdr did allocate that itself.
-------------------------------------------------*/
static int core_stdio_fclose_nonowner(core_file *file) {
free(file);
return 0;
}
/*-------------------------------------------------
core_stdio_fseek - core_file wrapper over fclose
-------------------------------------------------*/
static int core_stdio_fseek(core_file* file, INT64 offset, int whence) {
return core_stdio_fseek_impl((FILE*)file->argp, offset, whence);
}

View file

@ -60,9 +60,10 @@ int flac_decoder_init(flac_decoder *decoder)
void flac_decoder_free(flac_decoder* decoder)
{
if ((decoder != NULL) && (decoder->decoder != NULL))
if ((decoder != NULL) && (decoder->decoder != NULL)) {
drflac_close(decoder->decoder);
decoder->decoder = NULL;
decoder->decoder = NULL;
}
}
/*-------------------------------------------------

View file

@ -212,6 +212,8 @@ enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, stru
else
{
int repcount = bitstream_read(bitbuf, numbits) + 3;
if (repcount + curnode > decoder->numcodes)
return HUFFERR_INVALID_DATA;
while (repcount--)
decoder->huffnode[curnode++].numbits = nodebits;
}

View file

@ -320,7 +320,8 @@ CDImage::PrecacheResult CDImageCHD::Precache(ProgressCallback* progress)
static_cast<ProgressCallback*>(param)->SetProgressValue(std::min<u32>(percent, 100));
};
if (chd_precache_progress(m_chd, callback, progress) != CHDERR_NONE)
//if (chd_precache_progress(m_chd, callback, progress) != CHDERR_NONE)
if (chd_precache(m_chd) != CHDERR_NONE)
return CDImage::PrecacheResult::ReadError;
m_precached = true;