mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-29 00:55:41 +00:00
dep: Bump libchdr to 54bfb87
This commit is contained in:
parent
0798292ee5
commit
4b70853daa
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue