3rdparty: Move libchdr in-tree

Based on 54bfb87 with modifications from DuckStation.
This commit is contained in:
Stenzek 2023-09-25 22:56:40 +10:00 committed by Connor McLaughlin
parent 8ccd442647
commit 2148d3d3ab
22 changed files with 17892 additions and 21 deletions

3
.gitmodules vendored
View File

@ -7,9 +7,6 @@
[submodule "3rdparty/fmt/fmt"]
path = 3rdparty/fmt/fmt
url = https://github.com/fmtlib/fmt.git
[submodule "3rdparty/libchdr/libchdr"]
path = 3rdparty/libchdr/libchdr
url = https://github.com/rtissera/libchdr.git
[submodule "3rdparty/wil"]
path = 3rdparty/wil
url = https://github.com/microsoft/wil.git

View File

@ -1,11 +1,19 @@
add_library(chdr-static STATIC
libchdr/src/libchdr_bitstream.c
libchdr/src/libchdr_cdrom.c
libchdr/src/libchdr_chd.c
libchdr/src/libchdr_flac.c
libchdr/src/libchdr_huffman.c
add_library(libchdr
include/dr_libs/dr_flac.h
include/libchdr/bitstream.h
include/libchdr/cdrom.h
include/libchdr/chd.h
include/libchdr/chdconfig.h
include/libchdr/coretypes.h
include/libchdr/flac.h
include/libchdr/huffman.h
src/libchdr_bitstream.c
src/libchdr_cdrom.c
src/libchdr_chd.c
src/libchdr_flac.c
src/libchdr_huffman.c
)
target_include_directories(chdr-static PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/libchdr/include")
target_link_libraries(chdr-static PRIVATE ZLIB::ZLIB LZMA::LZMA)
target_compile_options(chdr-static PRIVATE "-w")
target_include_directories(libchdr PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(libchdr PRIVATE ZLIB::ZLIB LZMA::LZMA)

24
3rdparty/libchdr/LICENSE.txt vendored Normal file
View File

@ -0,0 +1,24 @@
Copyright Romain Tisserand
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

7
3rdparty/libchdr/README.md vendored Normal file
View File

@ -0,0 +1,7 @@
# libchdr
libchdr is a standalone library for reading MAME's CHDv1-v5 formats.
The code is based off of MAME's old C codebase which read up to CHDv4 with OS-dependent features removed, and CHDv5 support backported from MAME's current C++ codebase.
libchdr is licensed under the BSD 3-Clause (see [LICENSE.txt](LICENSE.txt)) and uses third party libraries that are each distributed under their own terms (see each library's license in [deps/](deps/)).

12507
3rdparty/libchdr/include/dr_libs/dr_flac.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
bitstream.h
Helper classes for reading/writing at the bit level.
***************************************************************************/
#pragma once
#ifndef __BITSTREAM_H__
#define __BITSTREAM_H__
#include <stdint.h>
/***************************************************************************
* TYPE DEFINITIONS
***************************************************************************
*/
/* helper class for reading from a bit buffer */
struct bitstream
{
uint32_t buffer; /* current bit accumulator */
int bits; /* number of bits in the accumulator */
const uint8_t * read; /* read pointer */
uint32_t doffset; /* byte offset within the data */
uint32_t dlength; /* length of the data */
};
struct bitstream* create_bitstream(const void *src, uint32_t srclength);
int bitstream_overflow(struct bitstream* bitstream);
uint32_t bitstream_read_offset(struct bitstream* bitstream);
uint32_t bitstream_read(struct bitstream* bitstream, int numbits);
uint32_t bitstream_peek(struct bitstream* bitstream, int numbits);
void bitstream_remove(struct bitstream* bitstream, int numbits);
uint32_t bitstream_flush(struct bitstream* bitstream);
#endif

110
3rdparty/libchdr/include/libchdr/cdrom.h vendored Normal file
View File

@ -0,0 +1,110 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
cdrom.h
Generic MAME cd-rom implementation
***************************************************************************/
#pragma once
#ifndef __CDROM_H__
#define __CDROM_H__
#include <stdint.h>
#include <libchdr/chdconfig.h>
/***************************************************************************
CONSTANTS
***************************************************************************/
/* tracks are padded to a multiple of this many frames */
#define CD_TRACK_PADDING (4)
#define CD_MAX_TRACKS (99) /* AFAIK the theoretical limit */
#define CD_MAX_SECTOR_DATA (2352)
#define CD_MAX_SUBCODE_DATA (96)
#define CD_FRAME_SIZE (CD_MAX_SECTOR_DATA + CD_MAX_SUBCODE_DATA)
#define CD_FRAMES_PER_HUNK (8)
#define CD_METADATA_WORDS (1+(CD_MAX_TRACKS * 6))
enum
{
CD_TRACK_MODE1 = 0, /* mode 1 2048 bytes/sector */
CD_TRACK_MODE1_RAW, /* mode 1 2352 bytes/sector */
CD_TRACK_MODE2, /* mode 2 2336 bytes/sector */
CD_TRACK_MODE2_FORM1, /* mode 2 2048 bytes/sector */
CD_TRACK_MODE2_FORM2, /* mode 2 2324 bytes/sector */
CD_TRACK_MODE2_FORM_MIX, /* mode 2 2336 bytes/sector */
CD_TRACK_MODE2_RAW, /* mode 2 2352 bytes / sector */
CD_TRACK_AUDIO, /* redbook audio track 2352 bytes/sector (588 samples) */
CD_TRACK_RAW_DONTCARE /* special flag for cdrom_read_data: just return me whatever is there */
};
enum
{
CD_SUB_NORMAL = 0, /* "cooked" 96 bytes per sector */
CD_SUB_RAW, /* raw uninterleaved 96 bytes per sector */
CD_SUB_NONE /* no subcode data stored */
};
#define CD_FLAG_GDROM 0x00000001 /* disc is a GD-ROM, all tracks should be stored with GD-ROM metadata */
#define CD_FLAG_GDROMLE 0x00000002 /* legacy GD-ROM, with little-endian CDDA data */
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
#ifdef WANT_RAW_DATA_SECTOR
/* ECC utilities */
int ecc_verify(const uint8_t *sector);
void ecc_generate(uint8_t *sector);
void ecc_clear(uint8_t *sector);
#endif
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
static inline uint32_t msf_to_lba(uint32_t msf)
{
return ( ((msf&0x00ff0000)>>16) * 60 * 75) + (((msf&0x0000ff00)>>8) * 75) + ((msf&0x000000ff)>>0);
}
static inline uint32_t lba_to_msf(uint32_t lba)
{
uint8_t m, s, f;
m = lba / (60 * 75);
lba -= m * (60 * 75);
s = lba / 75;
f = lba % 75;
return ((m / 10) << 20) | ((m % 10) << 16) |
((s / 10) << 12) | ((s % 10) << 8) |
((f / 10) << 4) | ((f % 10) << 0);
}
/**
* segacd needs it like this.. investigate
* Angelo also says PCE tracks often start playing at the
* wrong address.. related?
**/
static inline uint32_t lba_to_msf_alt(int lba)
{
uint32_t ret = 0;
ret |= ((lba / (60 * 75))&0xff)<<16;
ret |= (((lba / 75) % 60)&0xff)<<8;
ret |= ((lba % 75)&0xff)<<0;
return ret;
}
#endif /* __CDROM_H__ */

437
3rdparty/libchdr/include/libchdr/chd.h vendored Normal file
View File

@ -0,0 +1,437 @@
/***************************************************************************
chd.h
MAME Compressed Hunks of Data file format
****************************************************************************
Copyright Aaron Giles
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#pragma once
#ifndef __CHD_H__
#define __CHD_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <libchdr/coretypes.h>
#include <libchdr/chdconfig.h>
#include <stdbool.h>
/***************************************************************************
Compressed Hunks of Data header format. All numbers are stored in
Motorola (big-endian) byte ordering. The header is 76 (V1) or 80 (V2)
bytes long.
V1 header:
[ 0] char tag[8]; // 'MComprHD'
[ 8] UINT32 length; // length of header (including tag and length fields)
[ 12] UINT32 version; // drive format version
[ 16] UINT32 flags; // flags (see below)
[ 20] UINT32 compression; // compression type
[ 24] UINT32 hunksize; // 512-byte sectors per hunk
[ 28] UINT32 totalhunks; // total # of hunks represented
[ 32] UINT32 cylinders; // number of cylinders on hard disk
[ 36] UINT32 heads; // number of heads on hard disk
[ 40] UINT32 sectors; // number of sectors on hard disk
[ 44] UINT8 md5[16]; // MD5 checksum of raw data
[ 60] UINT8 parentmd5[16]; // MD5 checksum of parent file
[ 76] (V1 header length)
V2 header:
[ 0] char tag[8]; // 'MComprHD'
[ 8] UINT32 length; // length of header (including tag and length fields)
[ 12] UINT32 version; // drive format version
[ 16] UINT32 flags; // flags (see below)
[ 20] UINT32 compression; // compression type
[ 24] UINT32 hunksize; // seclen-byte sectors per hunk
[ 28] UINT32 totalhunks; // total # of hunks represented
[ 32] UINT32 cylinders; // number of cylinders on hard disk
[ 36] UINT32 heads; // number of heads on hard disk
[ 40] UINT32 sectors; // number of sectors on hard disk
[ 44] UINT8 md5[16]; // MD5 checksum of raw data
[ 60] UINT8 parentmd5[16]; // MD5 checksum of parent file
[ 76] UINT32 seclen; // number of bytes per sector
[ 80] (V2 header length)
V3 header:
[ 0] char tag[8]; // 'MComprHD'
[ 8] UINT32 length; // length of header (including tag and length fields)
[ 12] UINT32 version; // drive format version
[ 16] UINT32 flags; // flags (see below)
[ 20] UINT32 compression; // compression type
[ 24] UINT32 totalhunks; // total # of hunks represented
[ 28] UINT64 logicalbytes; // logical size of the data (in bytes)
[ 36] UINT64 metaoffset; // offset to the first blob of metadata
[ 44] UINT8 md5[16]; // MD5 checksum of raw data
[ 60] UINT8 parentmd5[16]; // MD5 checksum of parent file
[ 76] UINT32 hunkbytes; // number of bytes per hunk
[ 80] UINT8 sha1[20]; // SHA1 checksum of raw data
[100] UINT8 parentsha1[20];// SHA1 checksum of parent file
[120] (V3 header length)
V4 header:
[ 0] char tag[8]; // 'MComprHD'
[ 8] UINT32 length; // length of header (including tag and length fields)
[ 12] UINT32 version; // drive format version
[ 16] UINT32 flags; // flags (see below)
[ 20] UINT32 compression; // compression type
[ 24] UINT32 totalhunks; // total # of hunks represented
[ 28] UINT64 logicalbytes; // logical size of the data (in bytes)
[ 36] UINT64 metaoffset; // offset to the first blob of metadata
[ 44] UINT32 hunkbytes; // number of bytes per hunk
[ 48] UINT8 sha1[20]; // combined raw+meta SHA1
[ 68] UINT8 parentsha1[20];// combined raw+meta SHA1 of parent
[ 88] UINT8 rawsha1[20]; // raw data SHA1
[108] (V4 header length)
Flags:
0x00000001 - set if this drive has a parent
0x00000002 - set if this drive allows writes
=========================================================================
V5 header:
[ 0] char tag[8]; // 'MComprHD'
[ 8] uint32_t length; // length of header (including tag and length fields)
[ 12] uint32_t version; // drive format version
[ 16] uint32_t compressors[4];// which custom compressors are used?
[ 32] uint64_t logicalbytes; // logical size of the data (in bytes)
[ 40] uint64_t mapoffset; // offset to the map
[ 48] uint64_t metaoffset; // offset to the first blob of metadata
[ 56] uint32_t hunkbytes; // number of bytes per hunk (512k maximum)
[ 60] uint32_t unitbytes; // number of bytes per unit within each hunk
[ 64] uint8_t rawsha1[20]; // raw data SHA1
[ 84] uint8_t sha1[20]; // combined raw+meta SHA1
[104] uint8_t parentsha1[20];// combined raw+meta SHA1 of parent
[124] (V5 header length)
If parentsha1 != 0, we have a parent (no need for flags)
If compressors[0] == 0, we are uncompressed (including maps)
V5 uncompressed map format:
[ 0] uint32_t offset; // starting offset / hunk size
V5 compressed map format header:
[ 0] uint32_t length; // length of compressed map
[ 4] UINT48 datastart; // offset of first block
[ 10] uint16_t crc; // crc-16 of the map
[ 12] uint8_t lengthbits; // bits used to encode complength
[ 13] uint8_t hunkbits; // bits used to encode self-refs
[ 14] uint8_t parentunitbits; // bits used to encode parent unit refs
[ 15] uint8_t reserved; // future use
[ 16] (compressed header length)
Each compressed map entry, once expanded, looks like:
[ 0] uint8_t compression; // compression type
[ 1] UINT24 complength; // compressed length
[ 4] UINT48 offset; // offset
[ 10] uint16_t crc; // crc-16 of the data
***************************************************************************/
/***************************************************************************
CONSTANTS
***************************************************************************/
/* header information */
#define CHD_HEADER_VERSION 5
#define CHD_V1_HEADER_SIZE 76
#define CHD_V2_HEADER_SIZE 80
#define CHD_V3_HEADER_SIZE 120
#define CHD_V4_HEADER_SIZE 108
#define CHD_V5_HEADER_SIZE 124
#define CHD_MAX_HEADER_SIZE CHD_V5_HEADER_SIZE
/* checksumming information */
#define CHD_MD5_BYTES 16
#define CHD_SHA1_BYTES 20
/* CHD global flags */
#define CHDFLAGS_HAS_PARENT 0x00000001
#define CHDFLAGS_IS_WRITEABLE 0x00000002
#define CHDFLAGS_UNDEFINED 0xfffffffc
#define CHD_MAKE_TAG(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
/* compression types */
#define CHDCOMPRESSION_NONE 0
#define CHDCOMPRESSION_ZLIB 1
#define CHDCOMPRESSION_ZLIB_PLUS 2
#define CHDCOMPRESSION_AV 3
#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')
#define CHD_CODEC_CD_FLAC CHD_MAKE_TAG('c','d','f','l')
/* A/V codec configuration parameters */
#define AV_CODEC_COMPRESS_CONFIG 1
#define AV_CODEC_DECOMPRESS_CONFIG 2
/* metadata parameters */
#define CHDMETATAG_WILDCARD 0
#define CHD_METAINDEX_APPEND ((UINT32)-1)
/* metadata flags */
#define CHD_MDFLAGS_CHECKSUM 0x01 /* indicates data is checksummed */
/* standard hard disk metadata */
#define HARD_DISK_METADATA_TAG CHD_MAKE_TAG('G','D','D','D')
#define HARD_DISK_METADATA_FORMAT "CYLS:%d,HEADS:%d,SECS:%d,BPS:%d"
/* hard disk identify information */
#define HARD_DISK_IDENT_METADATA_TAG CHD_MAKE_TAG('I','D','N','T')
/* hard disk key information */
#define HARD_DISK_KEY_METADATA_TAG CHD_MAKE_TAG('K','E','Y',' ')
/* pcmcia CIS information */
#define PCMCIA_CIS_METADATA_TAG CHD_MAKE_TAG('C','I','S',' ')
/* standard CD-ROM metadata */
#define CDROM_OLD_METADATA_TAG CHD_MAKE_TAG('C','H','C','D')
#define CDROM_TRACK_METADATA_TAG CHD_MAKE_TAG('C','H','T','R')
#define CDROM_TRACK_METADATA_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d"
#define CDROM_TRACK_METADATA2_TAG CHD_MAKE_TAG('C','H','T','2')
#define CDROM_TRACK_METADATA2_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d"
#define GDROM_OLD_METADATA_TAG CHD_MAKE_TAG('C','H','G','T')
#define GDROM_TRACK_METADATA_TAG CHD_MAKE_TAG('C', 'H', 'G', 'D')
#define GDROM_TRACK_METADATA_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PAD:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d"
/* standard A/V metadata */
#define AV_METADATA_TAG CHD_MAKE_TAG('A','V','A','V')
#define AV_METADATA_FORMAT "FPS:%d.%06d WIDTH:%d HEIGHT:%d INTERLACED:%d CHANNELS:%d SAMPLERATE:%d"
/* A/V laserdisc frame metadata */
#define AV_LD_METADATA_TAG CHD_MAKE_TAG('A','V','L','D')
/* CHD open values */
#define CHD_OPEN_READ 1
#define CHD_OPEN_READWRITE 2
#define CHD_OPEN_TRANSFER_FILE 4 /* Freeing of the FILE* is now libchdr's responsibility if open was successful */
/* error types */
enum _chd_error
{
CHDERR_NONE,
CHDERR_NO_INTERFACE,
CHDERR_OUT_OF_MEMORY,
CHDERR_INVALID_FILE,
CHDERR_INVALID_PARAMETER,
CHDERR_INVALID_DATA,
CHDERR_FILE_NOT_FOUND,
CHDERR_REQUIRES_PARENT,
CHDERR_FILE_NOT_WRITEABLE,
CHDERR_READ_ERROR,
CHDERR_WRITE_ERROR,
CHDERR_CODEC_ERROR,
CHDERR_INVALID_PARENT,
CHDERR_HUNK_OUT_OF_RANGE,
CHDERR_DECOMPRESSION_ERROR,
CHDERR_COMPRESSION_ERROR,
CHDERR_CANT_CREATE_FILE,
CHDERR_CANT_VERIFY,
CHDERR_NOT_SUPPORTED,
CHDERR_METADATA_NOT_FOUND,
CHDERR_INVALID_METADATA_SIZE,
CHDERR_UNSUPPORTED_VERSION,
CHDERR_VERIFY_INCOMPLETE,
CHDERR_INVALID_METADATA,
CHDERR_INVALID_STATE,
CHDERR_OPERATION_PENDING,
CHDERR_NO_ASYNC_OPERATION,
CHDERR_UNSUPPORTED_FORMAT
};
typedef enum _chd_error chd_error;
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
/* opaque types */
typedef struct _chd_file chd_file;
/* extract header structure (NOT the on-disk header structure) */
typedef struct _chd_header chd_header;
struct _chd_header
{
UINT32 length; /* length of header data */
UINT32 version; /* drive format version */
UINT32 flags; /* flags field */
UINT32 compression[4]; /* compression type */
UINT32 hunkbytes; /* number of bytes per hunk */
UINT32 totalhunks; /* total # of hunks represented */
UINT64 logicalbytes; /* logical size of the data */
UINT64 metaoffset; /* offset in file of first metadata */
UINT64 mapoffset; /* TOOD V5 */
UINT8 md5[CHD_MD5_BYTES]; /* overall MD5 checksum */
UINT8 parentmd5[CHD_MD5_BYTES]; /* overall MD5 checksum of parent */
UINT8 sha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum */
UINT8 rawsha1[CHD_SHA1_BYTES]; /* SHA1 checksum of raw data */
UINT8 parentsha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum of parent */
UINT32 unitbytes; /* TODO V5 */
UINT64 unitcount; /* TODO V5 */
UINT32 hunkcount; /* TODO V5 */
/* map information */
UINT32 mapentrybytes; /* length of each entry in a map (V5) */
UINT8* rawmap; /* raw map data */
UINT32 obsolete_cylinders; /* obsolete field -- do not use! */
UINT32 obsolete_sectors; /* obsolete field -- do not use! */
UINT32 obsolete_heads; /* obsolete field -- do not use! */
UINT32 obsolete_hunksize; /* obsolete field -- do not use! */
};
/* structure for returning information about a verification pass */
typedef struct _chd_verify_result chd_verify_result;
struct _chd_verify_result
{
UINT8 md5[CHD_MD5_BYTES]; /* overall MD5 checksum */
UINT8 sha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum */
UINT8 rawsha1[CHD_SHA1_BYTES]; /* SHA1 checksum of raw data */
UINT8 metasha1[CHD_SHA1_BYTES]; /* SHA1 checksum of metadata */
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
#ifdef _MSC_VER
#ifdef CHD_DLL
#ifdef CHD_DLL_EXPORTS
#define CHD_EXPORT __declspec(dllexport)
#else
#define CHD_EXPORT __declspec(dllimport)
#endif
#else
#define CHD_EXPORT
#endif
#else
#define CHD_EXPORT __attribute__ ((visibility("default")))
#endif
/* ----- CHD file management ----- */
/* create a new CHD file fitting the given description */
/* chd_error chd_create(const char *filename, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent); */
/* same as chd_create(), but accepts an already-opened core_file object */
/* 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_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);
/* return the associated core_file */
CHD_EXPORT core_file *chd_core_file(chd_file *chd);
/* return an error string for the given CHD error */
CHD_EXPORT const char *chd_error_string(chd_error err);
/* ----- CHD header management ----- */
/* return a pointer to the extracted CHD header data */
CHD_EXPORT const chd_header *chd_get_header(chd_file *chd);
/* read CHD header data from file into the pointed struct */
CHD_EXPORT chd_error chd_read_header_core_file(core_file *file, chd_header *header);
CHD_EXPORT chd_error chd_read_header_file(FILE *file, chd_header *header);
CHD_EXPORT chd_error chd_read_header(const char *filename, chd_header *header);
CHD_EXPORT bool chd_is_matching_parent(const chd_header* header, const chd_header* parent_header);
/* ----- core data read/write ----- */
/* read one hunk from the CHD file */
CHD_EXPORT chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer);
/* ----- metadata management ----- */
/* get indexed metadata of a particular sort */
CHD_EXPORT chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags);
/* ----- codec interfaces ----- */
/* set internal codec parameters */
CHD_EXPORT chd_error chd_codec_config(chd_file *chd, int param, void *config);
/* return a string description of a codec */
CHD_EXPORT const char *chd_get_codec_name(UINT32 codec);
#ifdef __cplusplus
}
#endif
#endif /* __CHD_H__ */

View File

@ -0,0 +1,10 @@
#ifndef __CHDCONFIG_H__
#define __CHDCONFIG_H__
/* Configure CHDR features here */
#define WANT_RAW_DATA_SECTOR 1
#define WANT_SUBCODE 1
#define NEED_CACHE_HUNK 1
#define VERIFY_BLOCK_CRC 1
#endif

View File

@ -0,0 +1,78 @@
#ifndef __CORETYPES_H__
#define __CORETYPES_H__
#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;
typedef uint8_t UINT8;
typedef int64_t INT64;
typedef int32_t INT32;
typedef int16_t INT16;
typedef int8_t INT8;
typedef struct chd_core_file {
/*
* arbitrary pointer to data the implementation uses to implement the below functions
*/
void *argp;
/*
* 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*);
/*
* 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)
{
return fp->fsize(fp);
}
#endif

50
3rdparty/libchdr/include/libchdr/flac.h vendored Normal file
View File

@ -0,0 +1,50 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
flac.h
FLAC compression wrappers
***************************************************************************/
#pragma once
#ifndef __FLAC_H__
#define __FLAC_H__
#include <stdint.h>
/***************************************************************************
* TYPE DEFINITIONS
***************************************************************************
*/
typedef struct _flac_decoder flac_decoder;
struct _flac_decoder {
/* output state */
void * decoder; /* actual encoder */
uint32_t sample_rate; /* decoded sample rate */
uint8_t channels; /* decoded number of channels */
uint8_t bits_per_sample; /* decoded bits per sample */
uint32_t compressed_offset; /* current offset in compressed data */
const uint8_t * compressed_start; /* start of compressed data */
uint32_t compressed_length; /* length of compressed data */
const uint8_t * compressed2_start; /* start of compressed data */
uint32_t compressed2_length; /* length of compressed data */
int16_t * uncompressed_start[8]; /* pointer to start of uncompressed data (up to 8 streams) */
uint32_t uncompressed_offset; /* current position in uncompressed data */
uint32_t uncompressed_length; /* length of uncompressed data */
int uncompressed_swap; /* swap uncompressed sample data */
uint8_t custom_header[0x2a]; /* custom header */
};
/* ======================> flac_decoder */
int flac_decoder_init(flac_decoder* decoder);
void flac_decoder_free(flac_decoder* decoder);
int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_channels, uint32_t block_size, const void *buffer, uint32_t length);
int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian);
uint32_t flac_decoder_finish(flac_decoder* decoder);
#endif /* __FLAC_H__ */

View File

@ -0,0 +1,90 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
huffman.h
Static Huffman compression and decompression helpers.
***************************************************************************/
#pragma once
#ifndef __HUFFMAN_H__
#define __HUFFMAN_H__
#include <libchdr/bitstream.h>
/***************************************************************************
* CONSTANTS
***************************************************************************
*/
enum huffman_error
{
HUFFERR_NONE = 0,
HUFFERR_TOO_MANY_BITS,
HUFFERR_INVALID_DATA,
HUFFERR_INPUT_BUFFER_TOO_SMALL,
HUFFERR_OUTPUT_BUFFER_TOO_SMALL,
HUFFERR_INTERNAL_INCONSISTENCY,
HUFFERR_TOO_MANY_CONTEXTS
};
/***************************************************************************
* TYPE DEFINITIONS
***************************************************************************
*/
typedef uint16_t lookup_value;
/* a node in the huffman tree */
struct node_t
{
struct node_t* parent; /* pointer to parent node */
uint32_t count; /* number of hits on this node */
uint32_t weight; /* assigned weight of this node */
uint32_t bits; /* bits used to encode the node */
uint8_t numbits; /* number of bits needed for this node */
};
/* ======================> huffman_context_base */
/* context class for decoding */
struct huffman_decoder
{
/* internal state */
uint32_t numcodes; /* number of total codes being processed */
uint8_t maxbits; /* maximum bits per code */
uint8_t prevdata; /* value of the previous data (for delta-RLE encoding) */
int rleremaining; /* number of RLE bytes remaining (for delta-RLE encoding) */
lookup_value * lookup; /* pointer to the lookup table */
struct node_t * huffnode; /* array of nodes */
uint32_t * datahisto; /* histogram of data values */
/* array versions of the info we need */
#if 0
node_t* huffnode_array; /* [_NumCodes]; */
lookup_value* lookup_array; /* [1 << _MaxBits]; */
#endif
};
/* ======================> huffman_decoder */
struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits);
void delete_huffman_decoder(struct huffman_decoder* decoder);
/* single item operations */
uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* bitbuf);
enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, struct bitstream* bitbuf);
enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder, struct bitstream* bitbuf);
int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint32_t totalweight);
enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decoder);
enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decoder);
void huffman_build_lookup_table(struct huffman_decoder* decoder);
#endif

@ -1 +0,0 @@
Subproject commit fec8ab94212cc65d9d9a62cb3da924f5830c04b0

View File

@ -34,16 +34,16 @@
<ClCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);_7ZIP_ST</PreprocessorDefinitions>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<AdditionalIncludeDirectories>$(ProjectDir)libchdr\include;$(ProjectDir)\libchdr\src;$(SolutionDir)3rdparty\lzma\include;$(SolutionDir)3rdparty\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(ProjectDir)src;$(SolutionDir)3rdparty\lzma\include;$(SolutionDir)3rdparty\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="libchdr\src\libchdr_bitstream.c" />
<ClCompile Include="libchdr\src\libchdr_cdrom.c" />
<ClCompile Include="libchdr\src\libchdr_chd.c" />
<ClCompile Include="libchdr\src\libchdr_flac.c" />
<ClCompile Include="libchdr\src\libchdr_huffman.c" />
<ClCompile Include="src\libchdr_bitstream.c" />
<ClCompile Include="src\libchdr_cdrom.c" />
<ClCompile Include="src\libchdr_chd.c" />
<ClCompile Include="src\libchdr_flac.c" />
<ClCompile Include="src\libchdr_huffman.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\lzma\lzma.vcxproj">

125
3rdparty/libchdr/src/libchdr_bitstream.c vendored Normal file
View File

@ -0,0 +1,125 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
bitstream.c
Helper classes for reading/writing at the bit level.
***************************************************************************/
#include <stdlib.h>
#include <libchdr/bitstream.h>
/***************************************************************************
* INLINE FUNCTIONS
***************************************************************************
*/
int bitstream_overflow(struct bitstream* bitstream) { return ((bitstream->doffset - bitstream->bits / 8) > bitstream->dlength); }
/*-------------------------------------------------
* create_bitstream - constructor
*-------------------------------------------------
*/
struct bitstream* create_bitstream(const void *src, uint32_t srclength)
{
struct bitstream* bitstream = (struct bitstream*)malloc(sizeof(struct bitstream));
bitstream->buffer = 0;
bitstream->bits = 0;
bitstream->read = (const uint8_t*)src;
bitstream->doffset = 0;
bitstream->dlength = srclength;
return bitstream;
}
/*-----------------------------------------------------
* bitstream_peek - fetch the requested number of bits
* but don't advance the input pointer
*-----------------------------------------------------
*/
uint32_t bitstream_peek(struct bitstream* bitstream, int numbits)
{
if (numbits == 0)
return 0;
/* fetch data if we need more */
if (numbits > bitstream->bits)
{
while (bitstream->bits <= 24)
{
if (bitstream->doffset < bitstream->dlength)
bitstream->buffer |= bitstream->read[bitstream->doffset] << (24 - bitstream->bits);
bitstream->doffset++;
bitstream->bits += 8;
}
}
/* return the data */
return bitstream->buffer >> (32 - numbits);
}
/*-----------------------------------------------------
* bitstream_remove - advance the input pointer by the
* specified number of bits
*-----------------------------------------------------
*/
void bitstream_remove(struct bitstream* bitstream, int numbits)
{
bitstream->buffer <<= numbits;
bitstream->bits -= numbits;
}
/*-----------------------------------------------------
* bitstream_read - fetch the requested number of bits
*-----------------------------------------------------
*/
uint32_t bitstream_read(struct bitstream* bitstream, int numbits)
{
uint32_t result = bitstream_peek(bitstream, numbits);
bitstream_remove(bitstream, numbits);
return result;
}
/*-------------------------------------------------
* read_offset - return the current read offset
*-------------------------------------------------
*/
uint32_t bitstream_read_offset(struct bitstream* bitstream)
{
uint32_t result = bitstream->doffset;
int bits = bitstream->bits;
while (bits >= 8)
{
result--;
bits -= 8;
}
return result;
}
/*-------------------------------------------------
* flush - flush to the nearest byte
*-------------------------------------------------
*/
uint32_t bitstream_flush(struct bitstream* bitstream)
{
while (bitstream->bits >= 8)
{
bitstream->doffset--;
bitstream->bits -= 8;
}
bitstream->bits = bitstream->buffer = 0;
return bitstream->doffset;
}

415
3rdparty/libchdr/src/libchdr_cdrom.c vendored Normal file
View File

@ -0,0 +1,415 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
cdrom.c
Generic MAME CD-ROM utilties - build IDE and SCSI CD-ROMs on top of this
****************************************************************************
IMPORTANT:
"physical" block addresses are the actual addresses on the emulated CD.
"chd" block addresses are the block addresses in the CHD file.
Because we pad each track to a 4-frame boundary, these addressing
schemes will differ after track 1!
***************************************************************************/
#include <string.h>
#include <libchdr/cdrom.h>
#ifdef WANT_RAW_DATA_SECTOR
/***************************************************************************
DEBUGGING
***************************************************************************/
/** @brief The verbose. */
#define VERBOSE (0)
#if VERBOSE
/**
* @def LOG(x) do
*
* @brief A macro that defines log.
*
* @param x The void to process.
*/
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
/**
* @fn void CLIB_DECL logerror(const char *text, ...) ATTR_PRINTF(1,2);
*
* @brief Logerrors the given text.
*
* @param text The text.
*
* @return A CLIB_DECL.
*/
void CLIB_DECL logerror(const char *text, ...) ATTR_PRINTF(1,2);
#else
/**
* @def LOG(x);
*
* @brief A macro that defines log.
*
* @param x The void to process.
*/
#define LOG(x)
#endif
/***************************************************************************
CONSTANTS
***************************************************************************/
/** @brief offset within sector. */
#define SYNC_OFFSET 0x000
/** @brief 12 bytes. */
#define SYNC_NUM_BYTES 12
/** @brief offset within sector. */
#define MODE_OFFSET 0x00f
/** @brief offset within sector. */
#define ECC_P_OFFSET 0x81c
/** @brief 2 lots of 86. */
#define ECC_P_NUM_BYTES 86
/** @brief 24 bytes each. */
#define ECC_P_COMP 24
/** @brief The ECC q offset. */
#define ECC_Q_OFFSET (ECC_P_OFFSET + 2 * ECC_P_NUM_BYTES)
/** @brief 2 lots of 52. */
#define ECC_Q_NUM_BYTES 52
/** @brief 43 bytes each. */
#define ECC_Q_COMP 43
/**
* @brief -------------------------------------------------
* ECC lookup tables pre-calculated tables for ECC data calcs
* -------------------------------------------------.
*/
static const uint8_t ecclow[256] =
{
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
0x1d, 0x1f, 0x19, 0x1b, 0x15, 0x17, 0x11, 0x13, 0x0d, 0x0f, 0x09, 0x0b, 0x05, 0x07, 0x01, 0x03,
0x3d, 0x3f, 0x39, 0x3b, 0x35, 0x37, 0x31, 0x33, 0x2d, 0x2f, 0x29, 0x2b, 0x25, 0x27, 0x21, 0x23,
0x5d, 0x5f, 0x59, 0x5b, 0x55, 0x57, 0x51, 0x53, 0x4d, 0x4f, 0x49, 0x4b, 0x45, 0x47, 0x41, 0x43,
0x7d, 0x7f, 0x79, 0x7b, 0x75, 0x77, 0x71, 0x73, 0x6d, 0x6f, 0x69, 0x6b, 0x65, 0x67, 0x61, 0x63,
0x9d, 0x9f, 0x99, 0x9b, 0x95, 0x97, 0x91, 0x93, 0x8d, 0x8f, 0x89, 0x8b, 0x85, 0x87, 0x81, 0x83,
0xbd, 0xbf, 0xb9, 0xbb, 0xb5, 0xb7, 0xb1, 0xb3, 0xad, 0xaf, 0xa9, 0xab, 0xa5, 0xa7, 0xa1, 0xa3,
0xdd, 0xdf, 0xd9, 0xdb, 0xd5, 0xd7, 0xd1, 0xd3, 0xcd, 0xcf, 0xc9, 0xcb, 0xc5, 0xc7, 0xc1, 0xc3,
0xfd, 0xff, 0xf9, 0xfb, 0xf5, 0xf7, 0xf1, 0xf3, 0xed, 0xef, 0xe9, 0xeb, 0xe5, 0xe7, 0xe1, 0xe3
};
/** @brief The ecchigh[ 256]. */
static const uint8_t ecchigh[256] =
{
0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05,
0xfb, 0x0f, 0x0e, 0xfa, 0x0c, 0xf8, 0xf9, 0x0d, 0x08, 0xfc, 0xfd, 0x09, 0xff, 0x0b, 0x0a, 0xfe,
0xeb, 0x1f, 0x1e, 0xea, 0x1c, 0xe8, 0xe9, 0x1d, 0x18, 0xec, 0xed, 0x19, 0xef, 0x1b, 0x1a, 0xee,
0x10, 0xe4, 0xe5, 0x11, 0xe7, 0x13, 0x12, 0xe6, 0xe3, 0x17, 0x16, 0xe2, 0x14, 0xe0, 0xe1, 0x15,
0xcb, 0x3f, 0x3e, 0xca, 0x3c, 0xc8, 0xc9, 0x3d, 0x38, 0xcc, 0xcd, 0x39, 0xcf, 0x3b, 0x3a, 0xce,
0x30, 0xc4, 0xc5, 0x31, 0xc7, 0x33, 0x32, 0xc6, 0xc3, 0x37, 0x36, 0xc2, 0x34, 0xc0, 0xc1, 0x35,
0x20, 0xd4, 0xd5, 0x21, 0xd7, 0x23, 0x22, 0xd6, 0xd3, 0x27, 0x26, 0xd2, 0x24, 0xd0, 0xd1, 0x25,
0xdb, 0x2f, 0x2e, 0xda, 0x2c, 0xd8, 0xd9, 0x2d, 0x28, 0xdc, 0xdd, 0x29, 0xdf, 0x2b, 0x2a, 0xde,
0x8b, 0x7f, 0x7e, 0x8a, 0x7c, 0x88, 0x89, 0x7d, 0x78, 0x8c, 0x8d, 0x79, 0x8f, 0x7b, 0x7a, 0x8e,
0x70, 0x84, 0x85, 0x71, 0x87, 0x73, 0x72, 0x86, 0x83, 0x77, 0x76, 0x82, 0x74, 0x80, 0x81, 0x75,
0x60, 0x94, 0x95, 0x61, 0x97, 0x63, 0x62, 0x96, 0x93, 0x67, 0x66, 0x92, 0x64, 0x90, 0x91, 0x65,
0x9b, 0x6f, 0x6e, 0x9a, 0x6c, 0x98, 0x99, 0x6d, 0x68, 0x9c, 0x9d, 0x69, 0x9f, 0x6b, 0x6a, 0x9e,
0x40, 0xb4, 0xb5, 0x41, 0xb7, 0x43, 0x42, 0xb6, 0xb3, 0x47, 0x46, 0xb2, 0x44, 0xb0, 0xb1, 0x45,
0xbb, 0x4f, 0x4e, 0xba, 0x4c, 0xb8, 0xb9, 0x4d, 0x48, 0xbc, 0xbd, 0x49, 0xbf, 0x4b, 0x4a, 0xbe,
0xab, 0x5f, 0x5e, 0xaa, 0x5c, 0xa8, 0xa9, 0x5d, 0x58, 0xac, 0xad, 0x59, 0xaf, 0x5b, 0x5a, 0xae,
0x50, 0xa4, 0xa5, 0x51, 0xa7, 0x53, 0x52, 0xa6, 0xa3, 0x57, 0x56, 0xa2, 0x54, 0xa0, 0xa1, 0x55
};
/**
* @brief -------------------------------------------------
* poffsets - each row represents the addresses used to calculate a byte of the ECC P
* data 86 (*2) ECC P bytes, 24 values represented by each
* -------------------------------------------------.
*/
static const uint16_t poffsets[ECC_P_NUM_BYTES][ECC_P_COMP] =
{
{ 0x000,0x056,0x0ac,0x102,0x158,0x1ae,0x204,0x25a,0x2b0,0x306,0x35c,0x3b2,0x408,0x45e,0x4b4,0x50a,0x560,0x5b6,0x60c,0x662,0x6b8,0x70e,0x764,0x7ba },
{ 0x001,0x057,0x0ad,0x103,0x159,0x1af,0x205,0x25b,0x2b1,0x307,0x35d,0x3b3,0x409,0x45f,0x4b5,0x50b,0x561,0x5b7,0x60d,0x663,0x6b9,0x70f,0x765,0x7bb },
{ 0x002,0x058,0x0ae,0x104,0x15a,0x1b0,0x206,0x25c,0x2b2,0x308,0x35e,0x3b4,0x40a,0x460,0x4b6,0x50c,0x562,0x5b8,0x60e,0x664,0x6ba,0x710,0x766,0x7bc },
{ 0x003,0x059,0x0af,0x105,0x15b,0x1b1,0x207,0x25d,0x2b3,0x309,0x35f,0x3b5,0x40b,0x461,0x4b7,0x50d,0x563,0x5b9,0x60f,0x665,0x6bb,0x711,0x767,0x7bd },
{ 0x004,0x05a,0x0b0,0x106,0x15c,0x1b2,0x208,0x25e,0x2b4,0x30a,0x360,0x3b6,0x40c,0x462,0x4b8,0x50e,0x564,0x5ba,0x610,0x666,0x6bc,0x712,0x768,0x7be },
{ 0x005,0x05b,0x0b1,0x107,0x15d,0x1b3,0x209,0x25f,0x2b5,0x30b,0x361,0x3b7,0x40d,0x463,0x4b9,0x50f,0x565,0x5bb,0x611,0x667,0x6bd,0x713,0x769,0x7bf },
{ 0x006,0x05c,0x0b2,0x108,0x15e,0x1b4,0x20a,0x260,0x2b6,0x30c,0x362,0x3b8,0x40e,0x464,0x4ba,0x510,0x566,0x5bc,0x612,0x668,0x6be,0x714,0x76a,0x7c0 },
{ 0x007,0x05d,0x0b3,0x109,0x15f,0x1b5,0x20b,0x261,0x2b7,0x30d,0x363,0x3b9,0x40f,0x465,0x4bb,0x511,0x567,0x5bd,0x613,0x669,0x6bf,0x715,0x76b,0x7c1 },
{ 0x008,0x05e,0x0b4,0x10a,0x160,0x1b6,0x20c,0x262,0x2b8,0x30e,0x364,0x3ba,0x410,0x466,0x4bc,0x512,0x568,0x5be,0x614,0x66a,0x6c0,0x716,0x76c,0x7c2 },
{ 0x009,0x05f,0x0b5,0x10b,0x161,0x1b7,0x20d,0x263,0x2b9,0x30f,0x365,0x3bb,0x411,0x467,0x4bd,0x513,0x569,0x5bf,0x615,0x66b,0x6c1,0x717,0x76d,0x7c3 },
{ 0x00a,0x060,0x0b6,0x10c,0x162,0x1b8,0x20e,0x264,0x2ba,0x310,0x366,0x3bc,0x412,0x468,0x4be,0x514,0x56a,0x5c0,0x616,0x66c,0x6c2,0x718,0x76e,0x7c4 },
{ 0x00b,0x061,0x0b7,0x10d,0x163,0x1b9,0x20f,0x265,0x2bb,0x311,0x367,0x3bd,0x413,0x469,0x4bf,0x515,0x56b,0x5c1,0x617,0x66d,0x6c3,0x719,0x76f,0x7c5 },
{ 0x00c,0x062,0x0b8,0x10e,0x164,0x1ba,0x210,0x266,0x2bc,0x312,0x368,0x3be,0x414,0x46a,0x4c0,0x516,0x56c,0x5c2,0x618,0x66e,0x6c4,0x71a,0x770,0x7c6 },
{ 0x00d,0x063,0x0b9,0x10f,0x165,0x1bb,0x211,0x267,0x2bd,0x313,0x369,0x3bf,0x415,0x46b,0x4c1,0x517,0x56d,0x5c3,0x619,0x66f,0x6c5,0x71b,0x771,0x7c7 },
{ 0x00e,0x064,0x0ba,0x110,0x166,0x1bc,0x212,0x268,0x2be,0x314,0x36a,0x3c0,0x416,0x46c,0x4c2,0x518,0x56e,0x5c4,0x61a,0x670,0x6c6,0x71c,0x772,0x7c8 },
{ 0x00f,0x065,0x0bb,0x111,0x167,0x1bd,0x213,0x269,0x2bf,0x315,0x36b,0x3c1,0x417,0x46d,0x4c3,0x519,0x56f,0x5c5,0x61b,0x671,0x6c7,0x71d,0x773,0x7c9 },
{ 0x010,0x066,0x0bc,0x112,0x168,0x1be,0x214,0x26a,0x2c0,0x316,0x36c,0x3c2,0x418,0x46e,0x4c4,0x51a,0x570,0x5c6,0x61c,0x672,0x6c8,0x71e,0x774,0x7ca },
{ 0x011,0x067,0x0bd,0x113,0x169,0x1bf,0x215,0x26b,0x2c1,0x317,0x36d,0x3c3,0x419,0x46f,0x4c5,0x51b,0x571,0x5c7,0x61d,0x673,0x6c9,0x71f,0x775,0x7cb },
{ 0x012,0x068,0x0be,0x114,0x16a,0x1c0,0x216,0x26c,0x2c2,0x318,0x36e,0x3c4,0x41a,0x470,0x4c6,0x51c,0x572,0x5c8,0x61e,0x674,0x6ca,0x720,0x776,0x7cc },
{ 0x013,0x069,0x0bf,0x115,0x16b,0x1c1,0x217,0x26d,0x2c3,0x319,0x36f,0x3c5,0x41b,0x471,0x4c7,0x51d,0x573,0x5c9,0x61f,0x675,0x6cb,0x721,0x777,0x7cd },
{ 0x014,0x06a,0x0c0,0x116,0x16c,0x1c2,0x218,0x26e,0x2c4,0x31a,0x370,0x3c6,0x41c,0x472,0x4c8,0x51e,0x574,0x5ca,0x620,0x676,0x6cc,0x722,0x778,0x7ce },
{ 0x015,0x06b,0x0c1,0x117,0x16d,0x1c3,0x219,0x26f,0x2c5,0x31b,0x371,0x3c7,0x41d,0x473,0x4c9,0x51f,0x575,0x5cb,0x621,0x677,0x6cd,0x723,0x779,0x7cf },
{ 0x016,0x06c,0x0c2,0x118,0x16e,0x1c4,0x21a,0x270,0x2c6,0x31c,0x372,0x3c8,0x41e,0x474,0x4ca,0x520,0x576,0x5cc,0x622,0x678,0x6ce,0x724,0x77a,0x7d0 },
{ 0x017,0x06d,0x0c3,0x119,0x16f,0x1c5,0x21b,0x271,0x2c7,0x31d,0x373,0x3c9,0x41f,0x475,0x4cb,0x521,0x577,0x5cd,0x623,0x679,0x6cf,0x725,0x77b,0x7d1 },
{ 0x018,0x06e,0x0c4,0x11a,0x170,0x1c6,0x21c,0x272,0x2c8,0x31e,0x374,0x3ca,0x420,0x476,0x4cc,0x522,0x578,0x5ce,0x624,0x67a,0x6d0,0x726,0x77c,0x7d2 },
{ 0x019,0x06f,0x0c5,0x11b,0x171,0x1c7,0x21d,0x273,0x2c9,0x31f,0x375,0x3cb,0x421,0x477,0x4cd,0x523,0x579,0x5cf,0x625,0x67b,0x6d1,0x727,0x77d,0x7d3 },
{ 0x01a,0x070,0x0c6,0x11c,0x172,0x1c8,0x21e,0x274,0x2ca,0x320,0x376,0x3cc,0x422,0x478,0x4ce,0x524,0x57a,0x5d0,0x626,0x67c,0x6d2,0x728,0x77e,0x7d4 },
{ 0x01b,0x071,0x0c7,0x11d,0x173,0x1c9,0x21f,0x275,0x2cb,0x321,0x377,0x3cd,0x423,0x479,0x4cf,0x525,0x57b,0x5d1,0x627,0x67d,0x6d3,0x729,0x77f,0x7d5 },
{ 0x01c,0x072,0x0c8,0x11e,0x174,0x1ca,0x220,0x276,0x2cc,0x322,0x378,0x3ce,0x424,0x47a,0x4d0,0x526,0x57c,0x5d2,0x628,0x67e,0x6d4,0x72a,0x780,0x7d6 },
{ 0x01d,0x073,0x0c9,0x11f,0x175,0x1cb,0x221,0x277,0x2cd,0x323,0x379,0x3cf,0x425,0x47b,0x4d1,0x527,0x57d,0x5d3,0x629,0x67f,0x6d5,0x72b,0x781,0x7d7 },
{ 0x01e,0x074,0x0ca,0x120,0x176,0x1cc,0x222,0x278,0x2ce,0x324,0x37a,0x3d0,0x426,0x47c,0x4d2,0x528,0x57e,0x5d4,0x62a,0x680,0x6d6,0x72c,0x782,0x7d8 },
{ 0x01f,0x075,0x0cb,0x121,0x177,0x1cd,0x223,0x279,0x2cf,0x325,0x37b,0x3d1,0x427,0x47d,0x4d3,0x529,0x57f,0x5d5,0x62b,0x681,0x6d7,0x72d,0x783,0x7d9 },
{ 0x020,0x076,0x0cc,0x122,0x178,0x1ce,0x224,0x27a,0x2d0,0x326,0x37c,0x3d2,0x428,0x47e,0x4d4,0x52a,0x580,0x5d6,0x62c,0x682,0x6d8,0x72e,0x784,0x7da },
{ 0x021,0x077,0x0cd,0x123,0x179,0x1cf,0x225,0x27b,0x2d1,0x327,0x37d,0x3d3,0x429,0x47f,0x4d5,0x52b,0x581,0x5d7,0x62d,0x683,0x6d9,0x72f,0x785,0x7db },
{ 0x022,0x078,0x0ce,0x124,0x17a,0x1d0,0x226,0x27c,0x2d2,0x328,0x37e,0x3d4,0x42a,0x480,0x4d6,0x52c,0x582,0x5d8,0x62e,0x684,0x6da,0x730,0x786,0x7dc },
{ 0x023,0x079,0x0cf,0x125,0x17b,0x1d1,0x227,0x27d,0x2d3,0x329,0x37f,0x3d5,0x42b,0x481,0x4d7,0x52d,0x583,0x5d9,0x62f,0x685,0x6db,0x731,0x787,0x7dd },
{ 0x024,0x07a,0x0d0,0x126,0x17c,0x1d2,0x228,0x27e,0x2d4,0x32a,0x380,0x3d6,0x42c,0x482,0x4d8,0x52e,0x584,0x5da,0x630,0x686,0x6dc,0x732,0x788,0x7de },
{ 0x025,0x07b,0x0d1,0x127,0x17d,0x1d3,0x229,0x27f,0x2d5,0x32b,0x381,0x3d7,0x42d,0x483,0x4d9,0x52f,0x585,0x5db,0x631,0x687,0x6dd,0x733,0x789,0x7df },
{ 0x026,0x07c,0x0d2,0x128,0x17e,0x1d4,0x22a,0x280,0x2d6,0x32c,0x382,0x3d8,0x42e,0x484,0x4da,0x530,0x586,0x5dc,0x632,0x688,0x6de,0x734,0x78a,0x7e0 },
{ 0x027,0x07d,0x0d3,0x129,0x17f,0x1d5,0x22b,0x281,0x2d7,0x32d,0x383,0x3d9,0x42f,0x485,0x4db,0x531,0x587,0x5dd,0x633,0x689,0x6df,0x735,0x78b,0x7e1 },
{ 0x028,0x07e,0x0d4,0x12a,0x180,0x1d6,0x22c,0x282,0x2d8,0x32e,0x384,0x3da,0x430,0x486,0x4dc,0x532,0x588,0x5de,0x634,0x68a,0x6e0,0x736,0x78c,0x7e2 },
{ 0x029,0x07f,0x0d5,0x12b,0x181,0x1d7,0x22d,0x283,0x2d9,0x32f,0x385,0x3db,0x431,0x487,0x4dd,0x533,0x589,0x5df,0x635,0x68b,0x6e1,0x737,0x78d,0x7e3 },
{ 0x02a,0x080,0x0d6,0x12c,0x182,0x1d8,0x22e,0x284,0x2da,0x330,0x386,0x3dc,0x432,0x488,0x4de,0x534,0x58a,0x5e0,0x636,0x68c,0x6e2,0x738,0x78e,0x7e4 },
{ 0x02b,0x081,0x0d7,0x12d,0x183,0x1d9,0x22f,0x285,0x2db,0x331,0x387,0x3dd,0x433,0x489,0x4df,0x535,0x58b,0x5e1,0x637,0x68d,0x6e3,0x739,0x78f,0x7e5 },
{ 0x02c,0x082,0x0d8,0x12e,0x184,0x1da,0x230,0x286,0x2dc,0x332,0x388,0x3de,0x434,0x48a,0x4e0,0x536,0x58c,0x5e2,0x638,0x68e,0x6e4,0x73a,0x790,0x7e6 },
{ 0x02d,0x083,0x0d9,0x12f,0x185,0x1db,0x231,0x287,0x2dd,0x333,0x389,0x3df,0x435,0x48b,0x4e1,0x537,0x58d,0x5e3,0x639,0x68f,0x6e5,0x73b,0x791,0x7e7 },
{ 0x02e,0x084,0x0da,0x130,0x186,0x1dc,0x232,0x288,0x2de,0x334,0x38a,0x3e0,0x436,0x48c,0x4e2,0x538,0x58e,0x5e4,0x63a,0x690,0x6e6,0x73c,0x792,0x7e8 },
{ 0x02f,0x085,0x0db,0x131,0x187,0x1dd,0x233,0x289,0x2df,0x335,0x38b,0x3e1,0x437,0x48d,0x4e3,0x539,0x58f,0x5e5,0x63b,0x691,0x6e7,0x73d,0x793,0x7e9 },
{ 0x030,0x086,0x0dc,0x132,0x188,0x1de,0x234,0x28a,0x2e0,0x336,0x38c,0x3e2,0x438,0x48e,0x4e4,0x53a,0x590,0x5e6,0x63c,0x692,0x6e8,0x73e,0x794,0x7ea },
{ 0x031,0x087,0x0dd,0x133,0x189,0x1df,0x235,0x28b,0x2e1,0x337,0x38d,0x3e3,0x439,0x48f,0x4e5,0x53b,0x591,0x5e7,0x63d,0x693,0x6e9,0x73f,0x795,0x7eb },
{ 0x032,0x088,0x0de,0x134,0x18a,0x1e0,0x236,0x28c,0x2e2,0x338,0x38e,0x3e4,0x43a,0x490,0x4e6,0x53c,0x592,0x5e8,0x63e,0x694,0x6ea,0x740,0x796,0x7ec },
{ 0x033,0x089,0x0df,0x135,0x18b,0x1e1,0x237,0x28d,0x2e3,0x339,0x38f,0x3e5,0x43b,0x491,0x4e7,0x53d,0x593,0x5e9,0x63f,0x695,0x6eb,0x741,0x797,0x7ed },
{ 0x034,0x08a,0x0e0,0x136,0x18c,0x1e2,0x238,0x28e,0x2e4,0x33a,0x390,0x3e6,0x43c,0x492,0x4e8,0x53e,0x594,0x5ea,0x640,0x696,0x6ec,0x742,0x798,0x7ee },
{ 0x035,0x08b,0x0e1,0x137,0x18d,0x1e3,0x239,0x28f,0x2e5,0x33b,0x391,0x3e7,0x43d,0x493,0x4e9,0x53f,0x595,0x5eb,0x641,0x697,0x6ed,0x743,0x799,0x7ef },
{ 0x036,0x08c,0x0e2,0x138,0x18e,0x1e4,0x23a,0x290,0x2e6,0x33c,0x392,0x3e8,0x43e,0x494,0x4ea,0x540,0x596,0x5ec,0x642,0x698,0x6ee,0x744,0x79a,0x7f0 },
{ 0x037,0x08d,0x0e3,0x139,0x18f,0x1e5,0x23b,0x291,0x2e7,0x33d,0x393,0x3e9,0x43f,0x495,0x4eb,0x541,0x597,0x5ed,0x643,0x699,0x6ef,0x745,0x79b,0x7f1 },
{ 0x038,0x08e,0x0e4,0x13a,0x190,0x1e6,0x23c,0x292,0x2e8,0x33e,0x394,0x3ea,0x440,0x496,0x4ec,0x542,0x598,0x5ee,0x644,0x69a,0x6f0,0x746,0x79c,0x7f2 },
{ 0x039,0x08f,0x0e5,0x13b,0x191,0x1e7,0x23d,0x293,0x2e9,0x33f,0x395,0x3eb,0x441,0x497,0x4ed,0x543,0x599,0x5ef,0x645,0x69b,0x6f1,0x747,0x79d,0x7f3 },
{ 0x03a,0x090,0x0e6,0x13c,0x192,0x1e8,0x23e,0x294,0x2ea,0x340,0x396,0x3ec,0x442,0x498,0x4ee,0x544,0x59a,0x5f0,0x646,0x69c,0x6f2,0x748,0x79e,0x7f4 },
{ 0x03b,0x091,0x0e7,0x13d,0x193,0x1e9,0x23f,0x295,0x2eb,0x341,0x397,0x3ed,0x443,0x499,0x4ef,0x545,0x59b,0x5f1,0x647,0x69d,0x6f3,0x749,0x79f,0x7f5 },
{ 0x03c,0x092,0x0e8,0x13e,0x194,0x1ea,0x240,0x296,0x2ec,0x342,0x398,0x3ee,0x444,0x49a,0x4f0,0x546,0x59c,0x5f2,0x648,0x69e,0x6f4,0x74a,0x7a0,0x7f6 },
{ 0x03d,0x093,0x0e9,0x13f,0x195,0x1eb,0x241,0x297,0x2ed,0x343,0x399,0x3ef,0x445,0x49b,0x4f1,0x547,0x59d,0x5f3,0x649,0x69f,0x6f5,0x74b,0x7a1,0x7f7 },
{ 0x03e,0x094,0x0ea,0x140,0x196,0x1ec,0x242,0x298,0x2ee,0x344,0x39a,0x3f0,0x446,0x49c,0x4f2,0x548,0x59e,0x5f4,0x64a,0x6a0,0x6f6,0x74c,0x7a2,0x7f8 },
{ 0x03f,0x095,0x0eb,0x141,0x197,0x1ed,0x243,0x299,0x2ef,0x345,0x39b,0x3f1,0x447,0x49d,0x4f3,0x549,0x59f,0x5f5,0x64b,0x6a1,0x6f7,0x74d,0x7a3,0x7f9 },
{ 0x040,0x096,0x0ec,0x142,0x198,0x1ee,0x244,0x29a,0x2f0,0x346,0x39c,0x3f2,0x448,0x49e,0x4f4,0x54a,0x5a0,0x5f6,0x64c,0x6a2,0x6f8,0x74e,0x7a4,0x7fa },
{ 0x041,0x097,0x0ed,0x143,0x199,0x1ef,0x245,0x29b,0x2f1,0x347,0x39d,0x3f3,0x449,0x49f,0x4f5,0x54b,0x5a1,0x5f7,0x64d,0x6a3,0x6f9,0x74f,0x7a5,0x7fb },
{ 0x042,0x098,0x0ee,0x144,0x19a,0x1f0,0x246,0x29c,0x2f2,0x348,0x39e,0x3f4,0x44a,0x4a0,0x4f6,0x54c,0x5a2,0x5f8,0x64e,0x6a4,0x6fa,0x750,0x7a6,0x7fc },
{ 0x043,0x099,0x0ef,0x145,0x19b,0x1f1,0x247,0x29d,0x2f3,0x349,0x39f,0x3f5,0x44b,0x4a1,0x4f7,0x54d,0x5a3,0x5f9,0x64f,0x6a5,0x6fb,0x751,0x7a7,0x7fd },
{ 0x044,0x09a,0x0f0,0x146,0x19c,0x1f2,0x248,0x29e,0x2f4,0x34a,0x3a0,0x3f6,0x44c,0x4a2,0x4f8,0x54e,0x5a4,0x5fa,0x650,0x6a6,0x6fc,0x752,0x7a8,0x7fe },
{ 0x045,0x09b,0x0f1,0x147,0x19d,0x1f3,0x249,0x29f,0x2f5,0x34b,0x3a1,0x3f7,0x44d,0x4a3,0x4f9,0x54f,0x5a5,0x5fb,0x651,0x6a7,0x6fd,0x753,0x7a9,0x7ff },
{ 0x046,0x09c,0x0f2,0x148,0x19e,0x1f4,0x24a,0x2a0,0x2f6,0x34c,0x3a2,0x3f8,0x44e,0x4a4,0x4fa,0x550,0x5a6,0x5fc,0x652,0x6a8,0x6fe,0x754,0x7aa,0x800 },
{ 0x047,0x09d,0x0f3,0x149,0x19f,0x1f5,0x24b,0x2a1,0x2f7,0x34d,0x3a3,0x3f9,0x44f,0x4a5,0x4fb,0x551,0x5a7,0x5fd,0x653,0x6a9,0x6ff,0x755,0x7ab,0x801 },
{ 0x048,0x09e,0x0f4,0x14a,0x1a0,0x1f6,0x24c,0x2a2,0x2f8,0x34e,0x3a4,0x3fa,0x450,0x4a6,0x4fc,0x552,0x5a8,0x5fe,0x654,0x6aa,0x700,0x756,0x7ac,0x802 },
{ 0x049,0x09f,0x0f5,0x14b,0x1a1,0x1f7,0x24d,0x2a3,0x2f9,0x34f,0x3a5,0x3fb,0x451,0x4a7,0x4fd,0x553,0x5a9,0x5ff,0x655,0x6ab,0x701,0x757,0x7ad,0x803 },
{ 0x04a,0x0a0,0x0f6,0x14c,0x1a2,0x1f8,0x24e,0x2a4,0x2fa,0x350,0x3a6,0x3fc,0x452,0x4a8,0x4fe,0x554,0x5aa,0x600,0x656,0x6ac,0x702,0x758,0x7ae,0x804 },
{ 0x04b,0x0a1,0x0f7,0x14d,0x1a3,0x1f9,0x24f,0x2a5,0x2fb,0x351,0x3a7,0x3fd,0x453,0x4a9,0x4ff,0x555,0x5ab,0x601,0x657,0x6ad,0x703,0x759,0x7af,0x805 },
{ 0x04c,0x0a2,0x0f8,0x14e,0x1a4,0x1fa,0x250,0x2a6,0x2fc,0x352,0x3a8,0x3fe,0x454,0x4aa,0x500,0x556,0x5ac,0x602,0x658,0x6ae,0x704,0x75a,0x7b0,0x806 },
{ 0x04d,0x0a3,0x0f9,0x14f,0x1a5,0x1fb,0x251,0x2a7,0x2fd,0x353,0x3a9,0x3ff,0x455,0x4ab,0x501,0x557,0x5ad,0x603,0x659,0x6af,0x705,0x75b,0x7b1,0x807 },
{ 0x04e,0x0a4,0x0fa,0x150,0x1a6,0x1fc,0x252,0x2a8,0x2fe,0x354,0x3aa,0x400,0x456,0x4ac,0x502,0x558,0x5ae,0x604,0x65a,0x6b0,0x706,0x75c,0x7b2,0x808 },
{ 0x04f,0x0a5,0x0fb,0x151,0x1a7,0x1fd,0x253,0x2a9,0x2ff,0x355,0x3ab,0x401,0x457,0x4ad,0x503,0x559,0x5af,0x605,0x65b,0x6b1,0x707,0x75d,0x7b3,0x809 },
{ 0x050,0x0a6,0x0fc,0x152,0x1a8,0x1fe,0x254,0x2aa,0x300,0x356,0x3ac,0x402,0x458,0x4ae,0x504,0x55a,0x5b0,0x606,0x65c,0x6b2,0x708,0x75e,0x7b4,0x80a },
{ 0x051,0x0a7,0x0fd,0x153,0x1a9,0x1ff,0x255,0x2ab,0x301,0x357,0x3ad,0x403,0x459,0x4af,0x505,0x55b,0x5b1,0x607,0x65d,0x6b3,0x709,0x75f,0x7b5,0x80b },
{ 0x052,0x0a8,0x0fe,0x154,0x1aa,0x200,0x256,0x2ac,0x302,0x358,0x3ae,0x404,0x45a,0x4b0,0x506,0x55c,0x5b2,0x608,0x65e,0x6b4,0x70a,0x760,0x7b6,0x80c },
{ 0x053,0x0a9,0x0ff,0x155,0x1ab,0x201,0x257,0x2ad,0x303,0x359,0x3af,0x405,0x45b,0x4b1,0x507,0x55d,0x5b3,0x609,0x65f,0x6b5,0x70b,0x761,0x7b7,0x80d },
{ 0x054,0x0aa,0x100,0x156,0x1ac,0x202,0x258,0x2ae,0x304,0x35a,0x3b0,0x406,0x45c,0x4b2,0x508,0x55e,0x5b4,0x60a,0x660,0x6b6,0x70c,0x762,0x7b8,0x80e },
{ 0x055,0x0ab,0x101,0x157,0x1ad,0x203,0x259,0x2af,0x305,0x35b,0x3b1,0x407,0x45d,0x4b3,0x509,0x55f,0x5b5,0x60b,0x661,0x6b7,0x70d,0x763,0x7b9,0x80f }
};
/**
* @brief -------------------------------------------------
* qoffsets - each row represents the addresses used to calculate a byte of the ECC Q
* data 52 (*2) ECC Q bytes, 43 values represented by each
* -------------------------------------------------.
*/
static const uint16_t qoffsets[ECC_Q_NUM_BYTES][ECC_Q_COMP] =
{
{ 0x000,0x058,0x0b0,0x108,0x160,0x1b8,0x210,0x268,0x2c0,0x318,0x370,0x3c8,0x420,0x478,0x4d0,0x528,0x580,0x5d8,0x630,0x688,0x6e0,0x738,0x790,0x7e8,0x840,0x898,0x034,0x08c,0x0e4,0x13c,0x194,0x1ec,0x244,0x29c,0x2f4,0x34c,0x3a4,0x3fc,0x454,0x4ac,0x504,0x55c,0x5b4 },
{ 0x001,0x059,0x0b1,0x109,0x161,0x1b9,0x211,0x269,0x2c1,0x319,0x371,0x3c9,0x421,0x479,0x4d1,0x529,0x581,0x5d9,0x631,0x689,0x6e1,0x739,0x791,0x7e9,0x841,0x899,0x035,0x08d,0x0e5,0x13d,0x195,0x1ed,0x245,0x29d,0x2f5,0x34d,0x3a5,0x3fd,0x455,0x4ad,0x505,0x55d,0x5b5 },
{ 0x056,0x0ae,0x106,0x15e,0x1b6,0x20e,0x266,0x2be,0x316,0x36e,0x3c6,0x41e,0x476,0x4ce,0x526,0x57e,0x5d6,0x62e,0x686,0x6de,0x736,0x78e,0x7e6,0x83e,0x896,0x032,0x08a,0x0e2,0x13a,0x192,0x1ea,0x242,0x29a,0x2f2,0x34a,0x3a2,0x3fa,0x452,0x4aa,0x502,0x55a,0x5b2,0x60a },
{ 0x057,0x0af,0x107,0x15f,0x1b7,0x20f,0x267,0x2bf,0x317,0x36f,0x3c7,0x41f,0x477,0x4cf,0x527,0x57f,0x5d7,0x62f,0x687,0x6df,0x737,0x78f,0x7e7,0x83f,0x897,0x033,0x08b,0x0e3,0x13b,0x193,0x1eb,0x243,0x29b,0x2f3,0x34b,0x3a3,0x3fb,0x453,0x4ab,0x503,0x55b,0x5b3,0x60b },
{ 0x0ac,0x104,0x15c,0x1b4,0x20c,0x264,0x2bc,0x314,0x36c,0x3c4,0x41c,0x474,0x4cc,0x524,0x57c,0x5d4,0x62c,0x684,0x6dc,0x734,0x78c,0x7e4,0x83c,0x894,0x030,0x088,0x0e0,0x138,0x190,0x1e8,0x240,0x298,0x2f0,0x348,0x3a0,0x3f8,0x450,0x4a8,0x500,0x558,0x5b0,0x608,0x660 },
{ 0x0ad,0x105,0x15d,0x1b5,0x20d,0x265,0x2bd,0x315,0x36d,0x3c5,0x41d,0x475,0x4cd,0x525,0x57d,0x5d5,0x62d,0x685,0x6dd,0x735,0x78d,0x7e5,0x83d,0x895,0x031,0x089,0x0e1,0x139,0x191,0x1e9,0x241,0x299,0x2f1,0x349,0x3a1,0x3f9,0x451,0x4a9,0x501,0x559,0x5b1,0x609,0x661 },
{ 0x102,0x15a,0x1b2,0x20a,0x262,0x2ba,0x312,0x36a,0x3c2,0x41a,0x472,0x4ca,0x522,0x57a,0x5d2,0x62a,0x682,0x6da,0x732,0x78a,0x7e2,0x83a,0x892,0x02e,0x086,0x0de,0x136,0x18e,0x1e6,0x23e,0x296,0x2ee,0x346,0x39e,0x3f6,0x44e,0x4a6,0x4fe,0x556,0x5ae,0x606,0x65e,0x6b6 },
{ 0x103,0x15b,0x1b3,0x20b,0x263,0x2bb,0x313,0x36b,0x3c3,0x41b,0x473,0x4cb,0x523,0x57b,0x5d3,0x62b,0x683,0x6db,0x733,0x78b,0x7e3,0x83b,0x893,0x02f,0x087,0x0df,0x137,0x18f,0x1e7,0x23f,0x297,0x2ef,0x347,0x39f,0x3f7,0x44f,0x4a7,0x4ff,0x557,0x5af,0x607,0x65f,0x6b7 },
{ 0x158,0x1b0,0x208,0x260,0x2b8,0x310,0x368,0x3c0,0x418,0x470,0x4c8,0x520,0x578,0x5d0,0x628,0x680,0x6d8,0x730,0x788,0x7e0,0x838,0x890,0x02c,0x084,0x0dc,0x134,0x18c,0x1e4,0x23c,0x294,0x2ec,0x344,0x39c,0x3f4,0x44c,0x4a4,0x4fc,0x554,0x5ac,0x604,0x65c,0x6b4,0x70c },
{ 0x159,0x1b1,0x209,0x261,0x2b9,0x311,0x369,0x3c1,0x419,0x471,0x4c9,0x521,0x579,0x5d1,0x629,0x681,0x6d9,0x731,0x789,0x7e1,0x839,0x891,0x02d,0x085,0x0dd,0x135,0x18d,0x1e5,0x23d,0x295,0x2ed,0x345,0x39d,0x3f5,0x44d,0x4a5,0x4fd,0x555,0x5ad,0x605,0x65d,0x6b5,0x70d },
{ 0x1ae,0x206,0x25e,0x2b6,0x30e,0x366,0x3be,0x416,0x46e,0x4c6,0x51e,0x576,0x5ce,0x626,0x67e,0x6d6,0x72e,0x786,0x7de,0x836,0x88e,0x02a,0x082,0x0da,0x132,0x18a,0x1e2,0x23a,0x292,0x2ea,0x342,0x39a,0x3f2,0x44a,0x4a2,0x4fa,0x552,0x5aa,0x602,0x65a,0x6b2,0x70a,0x762 },
{ 0x1af,0x207,0x25f,0x2b7,0x30f,0x367,0x3bf,0x417,0x46f,0x4c7,0x51f,0x577,0x5cf,0x627,0x67f,0x6d7,0x72f,0x787,0x7df,0x837,0x88f,0x02b,0x083,0x0db,0x133,0x18b,0x1e3,0x23b,0x293,0x2eb,0x343,0x39b,0x3f3,0x44b,0x4a3,0x4fb,0x553,0x5ab,0x603,0x65b,0x6b3,0x70b,0x763 },
{ 0x204,0x25c,0x2b4,0x30c,0x364,0x3bc,0x414,0x46c,0x4c4,0x51c,0x574,0x5cc,0x624,0x67c,0x6d4,0x72c,0x784,0x7dc,0x834,0x88c,0x028,0x080,0x0d8,0x130,0x188,0x1e0,0x238,0x290,0x2e8,0x340,0x398,0x3f0,0x448,0x4a0,0x4f8,0x550,0x5a8,0x600,0x658,0x6b0,0x708,0x760,0x7b8 },
{ 0x205,0x25d,0x2b5,0x30d,0x365,0x3bd,0x415,0x46d,0x4c5,0x51d,0x575,0x5cd,0x625,0x67d,0x6d5,0x72d,0x785,0x7dd,0x835,0x88d,0x029,0x081,0x0d9,0x131,0x189,0x1e1,0x239,0x291,0x2e9,0x341,0x399,0x3f1,0x449,0x4a1,0x4f9,0x551,0x5a9,0x601,0x659,0x6b1,0x709,0x761,0x7b9 },
{ 0x25a,0x2b2,0x30a,0x362,0x3ba,0x412,0x46a,0x4c2,0x51a,0x572,0x5ca,0x622,0x67a,0x6d2,0x72a,0x782,0x7da,0x832,0x88a,0x026,0x07e,0x0d6,0x12e,0x186,0x1de,0x236,0x28e,0x2e6,0x33e,0x396,0x3ee,0x446,0x49e,0x4f6,0x54e,0x5a6,0x5fe,0x656,0x6ae,0x706,0x75e,0x7b6,0x80e },
{ 0x25b,0x2b3,0x30b,0x363,0x3bb,0x413,0x46b,0x4c3,0x51b,0x573,0x5cb,0x623,0x67b,0x6d3,0x72b,0x783,0x7db,0x833,0x88b,0x027,0x07f,0x0d7,0x12f,0x187,0x1df,0x237,0x28f,0x2e7,0x33f,0x397,0x3ef,0x447,0x49f,0x4f7,0x54f,0x5a7,0x5ff,0x657,0x6af,0x707,0x75f,0x7b7,0x80f },
{ 0x2b0,0x308,0x360,0x3b8,0x410,0x468,0x4c0,0x518,0x570,0x5c8,0x620,0x678,0x6d0,0x728,0x780,0x7d8,0x830,0x888,0x024,0x07c,0x0d4,0x12c,0x184,0x1dc,0x234,0x28c,0x2e4,0x33c,0x394,0x3ec,0x444,0x49c,0x4f4,0x54c,0x5a4,0x5fc,0x654,0x6ac,0x704,0x75c,0x7b4,0x80c,0x864 },
{ 0x2b1,0x309,0x361,0x3b9,0x411,0x469,0x4c1,0x519,0x571,0x5c9,0x621,0x679,0x6d1,0x729,0x781,0x7d9,0x831,0x889,0x025,0x07d,0x0d5,0x12d,0x185,0x1dd,0x235,0x28d,0x2e5,0x33d,0x395,0x3ed,0x445,0x49d,0x4f5,0x54d,0x5a5,0x5fd,0x655,0x6ad,0x705,0x75d,0x7b5,0x80d,0x865 },
{ 0x306,0x35e,0x3b6,0x40e,0x466,0x4be,0x516,0x56e,0x5c6,0x61e,0x676,0x6ce,0x726,0x77e,0x7d6,0x82e,0x886,0x022,0x07a,0x0d2,0x12a,0x182,0x1da,0x232,0x28a,0x2e2,0x33a,0x392,0x3ea,0x442,0x49a,0x4f2,0x54a,0x5a2,0x5fa,0x652,0x6aa,0x702,0x75a,0x7b2,0x80a,0x862,0x8ba },
{ 0x307,0x35f,0x3b7,0x40f,0x467,0x4bf,0x517,0x56f,0x5c7,0x61f,0x677,0x6cf,0x727,0x77f,0x7d7,0x82f,0x887,0x023,0x07b,0x0d3,0x12b,0x183,0x1db,0x233,0x28b,0x2e3,0x33b,0x393,0x3eb,0x443,0x49b,0x4f3,0x54b,0x5a3,0x5fb,0x653,0x6ab,0x703,0x75b,0x7b3,0x80b,0x863,0x8bb },
{ 0x35c,0x3b4,0x40c,0x464,0x4bc,0x514,0x56c,0x5c4,0x61c,0x674,0x6cc,0x724,0x77c,0x7d4,0x82c,0x884,0x020,0x078,0x0d0,0x128,0x180,0x1d8,0x230,0x288,0x2e0,0x338,0x390,0x3e8,0x440,0x498,0x4f0,0x548,0x5a0,0x5f8,0x650,0x6a8,0x700,0x758,0x7b0,0x808,0x860,0x8b8,0x054 },
{ 0x35d,0x3b5,0x40d,0x465,0x4bd,0x515,0x56d,0x5c5,0x61d,0x675,0x6cd,0x725,0x77d,0x7d5,0x82d,0x885,0x021,0x079,0x0d1,0x129,0x181,0x1d9,0x231,0x289,0x2e1,0x339,0x391,0x3e9,0x441,0x499,0x4f1,0x549,0x5a1,0x5f9,0x651,0x6a9,0x701,0x759,0x7b1,0x809,0x861,0x8b9,0x055 },
{ 0x3b2,0x40a,0x462,0x4ba,0x512,0x56a,0x5c2,0x61a,0x672,0x6ca,0x722,0x77a,0x7d2,0x82a,0x882,0x01e,0x076,0x0ce,0x126,0x17e,0x1d6,0x22e,0x286,0x2de,0x336,0x38e,0x3e6,0x43e,0x496,0x4ee,0x546,0x59e,0x5f6,0x64e,0x6a6,0x6fe,0x756,0x7ae,0x806,0x85e,0x8b6,0x052,0x0aa },
{ 0x3b3,0x40b,0x463,0x4bb,0x513,0x56b,0x5c3,0x61b,0x673,0x6cb,0x723,0x77b,0x7d3,0x82b,0x883,0x01f,0x077,0x0cf,0x127,0x17f,0x1d7,0x22f,0x287,0x2df,0x337,0x38f,0x3e7,0x43f,0x497,0x4ef,0x547,0x59f,0x5f7,0x64f,0x6a7,0x6ff,0x757,0x7af,0x807,0x85f,0x8b7,0x053,0x0ab },
{ 0x408,0x460,0x4b8,0x510,0x568,0x5c0,0x618,0x670,0x6c8,0x720,0x778,0x7d0,0x828,0x880,0x01c,0x074,0x0cc,0x124,0x17c,0x1d4,0x22c,0x284,0x2dc,0x334,0x38c,0x3e4,0x43c,0x494,0x4ec,0x544,0x59c,0x5f4,0x64c,0x6a4,0x6fc,0x754,0x7ac,0x804,0x85c,0x8b4,0x050,0x0a8,0x100 },
{ 0x409,0x461,0x4b9,0x511,0x569,0x5c1,0x619,0x671,0x6c9,0x721,0x779,0x7d1,0x829,0x881,0x01d,0x075,0x0cd,0x125,0x17d,0x1d5,0x22d,0x285,0x2dd,0x335,0x38d,0x3e5,0x43d,0x495,0x4ed,0x545,0x59d,0x5f5,0x64d,0x6a5,0x6fd,0x755,0x7ad,0x805,0x85d,0x8b5,0x051,0x0a9,0x101 },
{ 0x45e,0x4b6,0x50e,0x566,0x5be,0x616,0x66e,0x6c6,0x71e,0x776,0x7ce,0x826,0x87e,0x01a,0x072,0x0ca,0x122,0x17a,0x1d2,0x22a,0x282,0x2da,0x332,0x38a,0x3e2,0x43a,0x492,0x4ea,0x542,0x59a,0x5f2,0x64a,0x6a2,0x6fa,0x752,0x7aa,0x802,0x85a,0x8b2,0x04e,0x0a6,0x0fe,0x156 },
{ 0x45f,0x4b7,0x50f,0x567,0x5bf,0x617,0x66f,0x6c7,0x71f,0x777,0x7cf,0x827,0x87f,0x01b,0x073,0x0cb,0x123,0x17b,0x1d3,0x22b,0x283,0x2db,0x333,0x38b,0x3e3,0x43b,0x493,0x4eb,0x543,0x59b,0x5f3,0x64b,0x6a3,0x6fb,0x753,0x7ab,0x803,0x85b,0x8b3,0x04f,0x0a7,0x0ff,0x157 },
{ 0x4b4,0x50c,0x564,0x5bc,0x614,0x66c,0x6c4,0x71c,0x774,0x7cc,0x824,0x87c,0x018,0x070,0x0c8,0x120,0x178,0x1d0,0x228,0x280,0x2d8,0x330,0x388,0x3e0,0x438,0x490,0x4e8,0x540,0x598,0x5f0,0x648,0x6a0,0x6f8,0x750,0x7a8,0x800,0x858,0x8b0,0x04c,0x0a4,0x0fc,0x154,0x1ac },
{ 0x4b5,0x50d,0x565,0x5bd,0x615,0x66d,0x6c5,0x71d,0x775,0x7cd,0x825,0x87d,0x019,0x071,0x0c9,0x121,0x179,0x1d1,0x229,0x281,0x2d9,0x331,0x389,0x3e1,0x439,0x491,0x4e9,0x541,0x599,0x5f1,0x649,0x6a1,0x6f9,0x751,0x7a9,0x801,0x859,0x8b1,0x04d,0x0a5,0x0fd,0x155,0x1ad },
{ 0x50a,0x562,0x5ba,0x612,0x66a,0x6c2,0x71a,0x772,0x7ca,0x822,0x87a,0x016,0x06e,0x0c6,0x11e,0x176,0x1ce,0x226,0x27e,0x2d6,0x32e,0x386,0x3de,0x436,0x48e,0x4e6,0x53e,0x596,0x5ee,0x646,0x69e,0x6f6,0x74e,0x7a6,0x7fe,0x856,0x8ae,0x04a,0x0a2,0x0fa,0x152,0x1aa,0x202 },
{ 0x50b,0x563,0x5bb,0x613,0x66b,0x6c3,0x71b,0x773,0x7cb,0x823,0x87b,0x017,0x06f,0x0c7,0x11f,0x177,0x1cf,0x227,0x27f,0x2d7,0x32f,0x387,0x3df,0x437,0x48f,0x4e7,0x53f,0x597,0x5ef,0x647,0x69f,0x6f7,0x74f,0x7a7,0x7ff,0x857,0x8af,0x04b,0x0a3,0x0fb,0x153,0x1ab,0x203 },
{ 0x560,0x5b8,0x610,0x668,0x6c0,0x718,0x770,0x7c8,0x820,0x878,0x014,0x06c,0x0c4,0x11c,0x174,0x1cc,0x224,0x27c,0x2d4,0x32c,0x384,0x3dc,0x434,0x48c,0x4e4,0x53c,0x594,0x5ec,0x644,0x69c,0x6f4,0x74c,0x7a4,0x7fc,0x854,0x8ac,0x048,0x0a0,0x0f8,0x150,0x1a8,0x200,0x258 },
{ 0x561,0x5b9,0x611,0x669,0x6c1,0x719,0x771,0x7c9,0x821,0x879,0x015,0x06d,0x0c5,0x11d,0x175,0x1cd,0x225,0x27d,0x2d5,0x32d,0x385,0x3dd,0x435,0x48d,0x4e5,0x53d,0x595,0x5ed,0x645,0x69d,0x6f5,0x74d,0x7a5,0x7fd,0x855,0x8ad,0x049,0x0a1,0x0f9,0x151,0x1a9,0x201,0x259 },
{ 0x5b6,0x60e,0x666,0x6be,0x716,0x76e,0x7c6,0x81e,0x876,0x012,0x06a,0x0c2,0x11a,0x172,0x1ca,0x222,0x27a,0x2d2,0x32a,0x382,0x3da,0x432,0x48a,0x4e2,0x53a,0x592,0x5ea,0x642,0x69a,0x6f2,0x74a,0x7a2,0x7fa,0x852,0x8aa,0x046,0x09e,0x0f6,0x14e,0x1a6,0x1fe,0x256,0x2ae },
{ 0x5b7,0x60f,0x667,0x6bf,0x717,0x76f,0x7c7,0x81f,0x877,0x013,0x06b,0x0c3,0x11b,0x173,0x1cb,0x223,0x27b,0x2d3,0x32b,0x383,0x3db,0x433,0x48b,0x4e3,0x53b,0x593,0x5eb,0x643,0x69b,0x6f3,0x74b,0x7a3,0x7fb,0x853,0x8ab,0x047,0x09f,0x0f7,0x14f,0x1a7,0x1ff,0x257,0x2af },
{ 0x60c,0x664,0x6bc,0x714,0x76c,0x7c4,0x81c,0x874,0x010,0x068,0x0c0,0x118,0x170,0x1c8,0x220,0x278,0x2d0,0x328,0x380,0x3d8,0x430,0x488,0x4e0,0x538,0x590,0x5e8,0x640,0x698,0x6f0,0x748,0x7a0,0x7f8,0x850,0x8a8,0x044,0x09c,0x0f4,0x14c,0x1a4,0x1fc,0x254,0x2ac,0x304 },
{ 0x60d,0x665,0x6bd,0x715,0x76d,0x7c5,0x81d,0x875,0x011,0x069,0x0c1,0x119,0x171,0x1c9,0x221,0x279,0x2d1,0x329,0x381,0x3d9,0x431,0x489,0x4e1,0x539,0x591,0x5e9,0x641,0x699,0x6f1,0x749,0x7a1,0x7f9,0x851,0x8a9,0x045,0x09d,0x0f5,0x14d,0x1a5,0x1fd,0x255,0x2ad,0x305 },
{ 0x662,0x6ba,0x712,0x76a,0x7c2,0x81a,0x872,0x00e,0x066,0x0be,0x116,0x16e,0x1c6,0x21e,0x276,0x2ce,0x326,0x37e,0x3d6,0x42e,0x486,0x4de,0x536,0x58e,0x5e6,0x63e,0x696,0x6ee,0x746,0x79e,0x7f6,0x84e,0x8a6,0x042,0x09a,0x0f2,0x14a,0x1a2,0x1fa,0x252,0x2aa,0x302,0x35a },
{ 0x663,0x6bb,0x713,0x76b,0x7c3,0x81b,0x873,0x00f,0x067,0x0bf,0x117,0x16f,0x1c7,0x21f,0x277,0x2cf,0x327,0x37f,0x3d7,0x42f,0x487,0x4df,0x537,0x58f,0x5e7,0x63f,0x697,0x6ef,0x747,0x79f,0x7f7,0x84f,0x8a7,0x043,0x09b,0x0f3,0x14b,0x1a3,0x1fb,0x253,0x2ab,0x303,0x35b },
{ 0x6b8,0x710,0x768,0x7c0,0x818,0x870,0x00c,0x064,0x0bc,0x114,0x16c,0x1c4,0x21c,0x274,0x2cc,0x324,0x37c,0x3d4,0x42c,0x484,0x4dc,0x534,0x58c,0x5e4,0x63c,0x694,0x6ec,0x744,0x79c,0x7f4,0x84c,0x8a4,0x040,0x098,0x0f0,0x148,0x1a0,0x1f8,0x250,0x2a8,0x300,0x358,0x3b0 },
{ 0x6b9,0x711,0x769,0x7c1,0x819,0x871,0x00d,0x065,0x0bd,0x115,0x16d,0x1c5,0x21d,0x275,0x2cd,0x325,0x37d,0x3d5,0x42d,0x485,0x4dd,0x535,0x58d,0x5e5,0x63d,0x695,0x6ed,0x745,0x79d,0x7f5,0x84d,0x8a5,0x041,0x099,0x0f1,0x149,0x1a1,0x1f9,0x251,0x2a9,0x301,0x359,0x3b1 },
{ 0x70e,0x766,0x7be,0x816,0x86e,0x00a,0x062,0x0ba,0x112,0x16a,0x1c2,0x21a,0x272,0x2ca,0x322,0x37a,0x3d2,0x42a,0x482,0x4da,0x532,0x58a,0x5e2,0x63a,0x692,0x6ea,0x742,0x79a,0x7f2,0x84a,0x8a2,0x03e,0x096,0x0ee,0x146,0x19e,0x1f6,0x24e,0x2a6,0x2fe,0x356,0x3ae,0x406 },
{ 0x70f,0x767,0x7bf,0x817,0x86f,0x00b,0x063,0x0bb,0x113,0x16b,0x1c3,0x21b,0x273,0x2cb,0x323,0x37b,0x3d3,0x42b,0x483,0x4db,0x533,0x58b,0x5e3,0x63b,0x693,0x6eb,0x743,0x79b,0x7f3,0x84b,0x8a3,0x03f,0x097,0x0ef,0x147,0x19f,0x1f7,0x24f,0x2a7,0x2ff,0x357,0x3af,0x407 },
{ 0x764,0x7bc,0x814,0x86c,0x008,0x060,0x0b8,0x110,0x168,0x1c0,0x218,0x270,0x2c8,0x320,0x378,0x3d0,0x428,0x480,0x4d8,0x530,0x588,0x5e0,0x638,0x690,0x6e8,0x740,0x798,0x7f0,0x848,0x8a0,0x03c,0x094,0x0ec,0x144,0x19c,0x1f4,0x24c,0x2a4,0x2fc,0x354,0x3ac,0x404,0x45c },
{ 0x765,0x7bd,0x815,0x86d,0x009,0x061,0x0b9,0x111,0x169,0x1c1,0x219,0x271,0x2c9,0x321,0x379,0x3d1,0x429,0x481,0x4d9,0x531,0x589,0x5e1,0x639,0x691,0x6e9,0x741,0x799,0x7f1,0x849,0x8a1,0x03d,0x095,0x0ed,0x145,0x19d,0x1f5,0x24d,0x2a5,0x2fd,0x355,0x3ad,0x405,0x45d },
{ 0x7ba,0x812,0x86a,0x006,0x05e,0x0b6,0x10e,0x166,0x1be,0x216,0x26e,0x2c6,0x31e,0x376,0x3ce,0x426,0x47e,0x4d6,0x52e,0x586,0x5de,0x636,0x68e,0x6e6,0x73e,0x796,0x7ee,0x846,0x89e,0x03a,0x092,0x0ea,0x142,0x19a,0x1f2,0x24a,0x2a2,0x2fa,0x352,0x3aa,0x402,0x45a,0x4b2 },
{ 0x7bb,0x813,0x86b,0x007,0x05f,0x0b7,0x10f,0x167,0x1bf,0x217,0x26f,0x2c7,0x31f,0x377,0x3cf,0x427,0x47f,0x4d7,0x52f,0x587,0x5df,0x637,0x68f,0x6e7,0x73f,0x797,0x7ef,0x847,0x89f,0x03b,0x093,0x0eb,0x143,0x19b,0x1f3,0x24b,0x2a3,0x2fb,0x353,0x3ab,0x403,0x45b,0x4b3 },
{ 0x810,0x868,0x004,0x05c,0x0b4,0x10c,0x164,0x1bc,0x214,0x26c,0x2c4,0x31c,0x374,0x3cc,0x424,0x47c,0x4d4,0x52c,0x584,0x5dc,0x634,0x68c,0x6e4,0x73c,0x794,0x7ec,0x844,0x89c,0x038,0x090,0x0e8,0x140,0x198,0x1f0,0x248,0x2a0,0x2f8,0x350,0x3a8,0x400,0x458,0x4b0,0x508 },
{ 0x811,0x869,0x005,0x05d,0x0b5,0x10d,0x165,0x1bd,0x215,0x26d,0x2c5,0x31d,0x375,0x3cd,0x425,0x47d,0x4d5,0x52d,0x585,0x5dd,0x635,0x68d,0x6e5,0x73d,0x795,0x7ed,0x845,0x89d,0x039,0x091,0x0e9,0x141,0x199,0x1f1,0x249,0x2a1,0x2f9,0x351,0x3a9,0x401,0x459,0x4b1,0x509 },
{ 0x866,0x002,0x05a,0x0b2,0x10a,0x162,0x1ba,0x212,0x26a,0x2c2,0x31a,0x372,0x3ca,0x422,0x47a,0x4d2,0x52a,0x582,0x5da,0x632,0x68a,0x6e2,0x73a,0x792,0x7ea,0x842,0x89a,0x036,0x08e,0x0e6,0x13e,0x196,0x1ee,0x246,0x29e,0x2f6,0x34e,0x3a6,0x3fe,0x456,0x4ae,0x506,0x55e },
{ 0x867,0x003,0x05b,0x0b3,0x10b,0x163,0x1bb,0x213,0x26b,0x2c3,0x31b,0x373,0x3cb,0x423,0x47b,0x4d3,0x52b,0x583,0x5db,0x633,0x68b,0x6e3,0x73b,0x793,0x7eb,0x843,0x89b,0x037,0x08f,0x0e7,0x13f,0x197,0x1ef,0x247,0x29f,0x2f7,0x34f,0x3a7,0x3ff,0x457,0x4af,0x507,0x55f }
};
/*-------------------------------------------------
* ecc_source_byte - return data from the sector
* at the given offset, masking anything
* particular to a mode
*-------------------------------------------------
*/
static inline uint8_t ecc_source_byte(const uint8_t *sector, uint32_t offset)
{
/* in mode 2 always treat these as 0 bytes */
return (sector[MODE_OFFSET] == 2 && offset < 4) ? 0x00 : sector[SYNC_OFFSET + SYNC_NUM_BYTES + offset];
}
/**
* @fn void ecc_compute_bytes(const uint8_t *sector, const uint16_t *row, int rowlen, uint8_t &val1, uint8_t &val2)
*
* @brief -------------------------------------------------
* ecc_compute_bytes - calculate an ECC value (P or Q)
* -------------------------------------------------.
*
* @param sector The sector.
* @param row The row.
* @param rowlen The rowlen.
* @param [in,out] val1 The first value.
* @param [in,out] val2 The second value.
*/
void ecc_compute_bytes(const uint8_t *sector, const uint16_t *row, int rowlen, uint8_t *val1, uint8_t *val2)
{
int component;
*val1 = *val2 = 0;
for (component = 0; component < rowlen; component++)
{
*val1 ^= ecc_source_byte(sector, row[component]);
*val2 ^= ecc_source_byte(sector, row[component]);
*val1 = ecclow[*val1];
}
*val1 = ecchigh[ecclow[*val1] ^ *val2];
*val2 ^= *val1;
}
/**
* @fn int ecc_verify(const uint8_t *sector)
*
* @brief -------------------------------------------------
* ecc_verify - verify the P and Q ECC codes in a sector
* -------------------------------------------------.
*
* @param sector The sector.
*
* @return true if it succeeds, false if it fails.
*/
int ecc_verify(const uint8_t *sector)
{
int byte;
/* first verify P bytes */
for (byte = 0; byte < ECC_P_NUM_BYTES; byte++)
{
uint8_t val1, val2;
ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, &val1, &val2);
if (sector[ECC_P_OFFSET + byte] != val1 || sector[ECC_P_OFFSET + ECC_P_NUM_BYTES + byte] != val2)
return 0;
}
/* then verify Q bytes */
for (byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
{
uint8_t val1, val2;
ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, &val1, &val2);
if (sector[ECC_Q_OFFSET + byte] != val1 || sector[ECC_Q_OFFSET + ECC_Q_NUM_BYTES + byte] != val2)
return 0;
}
return 1;
}
/**
* @fn void ecc_generate(uint8_t *sector)
*
* @brief -------------------------------------------------
* ecc_generate - generate the P and Q ECC codes for a sector, overwriting any
* existing codes
* -------------------------------------------------.
*
* @param [in,out] sector If non-null, the sector.
*/
void ecc_generate(uint8_t *sector)
{
int byte;
/* first verify P bytes */
for (byte = 0; byte < ECC_P_NUM_BYTES; byte++)
ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, &sector[ECC_P_OFFSET + byte], &sector[ECC_P_OFFSET + ECC_P_NUM_BYTES + byte]);
/* then verify Q bytes */
for (byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, &sector[ECC_Q_OFFSET + byte], &sector[ECC_Q_OFFSET + ECC_Q_NUM_BYTES + byte]);
}
/**
* @fn void ecc_clear(uint8_t *sector)
*
* @brief -------------------------------------------------
* ecc_clear - erase the ECC P and Q cods to 0 within a sector
* -------------------------------------------------.
*
* @param [in,out] sector If non-null, the sector.
*/
void ecc_clear(uint8_t *sector)
{
memset(&sector[ECC_P_OFFSET], 0, 2 * ECC_P_NUM_BYTES);
memset(&sector[ECC_Q_OFFSET], 0, 2 * ECC_Q_NUM_BYTES);
}
#endif /* WANT_RAW_DATA_SECTOR */

3120
3rdparty/libchdr/src/libchdr_chd.c vendored Normal file

File diff suppressed because it is too large Load Diff

303
3rdparty/libchdr/src/libchdr_flac.c vendored Normal file
View File

@ -0,0 +1,303 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
flac.c
FLAC compression wrappers
***************************************************************************/
#include <string.h>
#include <libchdr/flac.h>
#define DR_FLAC_IMPLEMENTATION
#define DR_FLAC_NO_STDIO
#include <dr_libs/dr_flac.h>
/***************************************************************************
* FLAC DECODER
***************************************************************************
*/
static size_t flac_decoder_read_callback(void *userdata, void *buffer, size_t bytes);
static drflac_bool32 flac_decoder_seek_callback(void *userdata, int offset, drflac_seek_origin origin);
static void flac_decoder_metadata_callback(void *userdata, drflac_metadata *metadata);
static void flac_decoder_write_callback(void *userdata, void *buffer, size_t bytes);
/* getters (valid after reset) */
static uint32_t sample_rate(flac_decoder *decoder) { return decoder->sample_rate; }
static uint8_t channels(flac_decoder *decoder) { return decoder->channels; }
static uint8_t bits_per_sample(flac_decoder *decoder) { return decoder->bits_per_sample; }
/*-------------------------------------------------
* flac_decoder - constructor
*-------------------------------------------------
*/
int flac_decoder_init(flac_decoder *decoder)
{
decoder->decoder = NULL;
decoder->sample_rate = 0;
decoder->channels = 0;
decoder->bits_per_sample = 0;
decoder->compressed_offset = 0;
decoder->compressed_start = NULL;
decoder->compressed_length = 0;
decoder->compressed2_start = NULL;
decoder->compressed2_length = 0;
decoder->uncompressed_offset = 0;
decoder->uncompressed_length = 0;
decoder->uncompressed_swap = 0;
return 0;
}
/*-------------------------------------------------
* flac_decoder - destructor
*-------------------------------------------------
*/
void flac_decoder_free(flac_decoder* decoder)
{
if ((decoder != NULL) && (decoder->decoder != NULL)) {
drflac_close(decoder->decoder);
decoder->decoder = NULL;
}
}
/*-------------------------------------------------
* reset - reset state with the original
* parameters
*-------------------------------------------------
*/
static int flac_decoder_internal_reset(flac_decoder* decoder)
{
decoder->compressed_offset = 0;
flac_decoder_free(decoder);
decoder->decoder = drflac_open_with_metadata(
flac_decoder_read_callback, flac_decoder_seek_callback,
flac_decoder_metadata_callback, decoder, NULL);
return (decoder->decoder != NULL);
}
/*-------------------------------------------------
* reset - reset state with new memory parameters
* and a custom-generated header
*-------------------------------------------------
*/
int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_channels, uint32_t block_size, const void *buffer, uint32_t length)
{
/* modify the template header with our parameters */
static const uint8_t s_header_template[0x2a] =
{
0x66, 0x4C, 0x61, 0x43, /* +00: 'fLaC' stream header */
0x80, /* +04: metadata block type 0 (STREAMINFO), */
/* flagged as last block */
0x00, 0x00, 0x22, /* +05: metadata block length = 0x22 */
0x00, 0x00, /* +08: minimum block size */
0x00, 0x00, /* +0A: maximum block size */
0x00, 0x00, 0x00, /* +0C: minimum frame size (0 == unknown) */
0x00, 0x00, 0x00, /* +0F: maximum frame size (0 == unknown) */
0x0A, 0xC4, 0x42, 0xF0, 0x00, 0x00, 0x00, 0x00, /* +12: sample rate (0x0ac44 == 44100), */
/* numchannels (2), sample bits (16), */
/* samples in stream (0 == unknown) */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* +1A: MD5 signature (0 == none) */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* +2A: start of stream data */
};
memcpy(decoder->custom_header, s_header_template, sizeof(s_header_template));
decoder->custom_header[0x08] = decoder->custom_header[0x0a] = (block_size*num_channels) >> 8;
decoder->custom_header[0x09] = decoder->custom_header[0x0b] = (block_size*num_channels) & 0xff;
decoder->custom_header[0x12] = sample_rate >> 12;
decoder->custom_header[0x13] = sample_rate >> 4;
decoder->custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1);
/* configure the header ahead of the provided buffer */
decoder->compressed_start = (const uint8_t *)(decoder->custom_header);
decoder->compressed_length = sizeof(decoder->custom_header);
decoder->compressed2_start = (const uint8_t *)(buffer);
decoder->compressed2_length = length;
return flac_decoder_internal_reset(decoder);
}
/*-------------------------------------------------
* decode_interleaved - decode to an interleaved
* sound stream
*-------------------------------------------------
*/
int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian)
{
/* configure the uncompressed buffer */
memset(decoder->uncompressed_start, 0, sizeof(decoder->uncompressed_start));
decoder->uncompressed_start[0] = samples;
decoder->uncompressed_offset = 0;
decoder->uncompressed_length = num_samples;
decoder->uncompressed_swap = swap_endian;
#define BUFFER 2352 /* bytes per CD audio sector */
int16_t buffer[BUFFER];
uint32_t buf_samples = BUFFER / channels(decoder);
/* loop until we get everything we want */
while (decoder->uncompressed_offset < decoder->uncompressed_length) {
uint32_t frames = (num_samples < buf_samples ? num_samples : buf_samples);
if (!drflac_read_pcm_frames_s16(decoder->decoder, frames, buffer))
return 0;
flac_decoder_write_callback(decoder, buffer, frames*sizeof(*buffer)*channels(decoder));
num_samples -= frames;
}
return 1;
}
/*-------------------------------------------------
* finish - finish up the decode
*-------------------------------------------------
*/
uint32_t flac_decoder_finish(flac_decoder* decoder)
{
/* get the final decoding position and move forward */
drflac *flac = decoder->decoder;
uint64_t position = decoder->compressed_offset;
/* ugh... there's no function to obtain bytes used in drflac :-/ */
position -= DRFLAC_CACHE_L2_LINES_REMAINING(&flac->bs) * sizeof(drflac_cache_t);
position -= DRFLAC_CACHE_L1_BITS_REMAINING(&flac->bs) / 8;
position -= flac->bs.unalignedByteCount;
/* adjust position if we provided the header */
if (position == 0)
return 0;
if (decoder->compressed_start == (const uint8_t *)(decoder->custom_header))
position -= decoder->compressed_length;
flac_decoder_free(decoder);
return position;
}
/*-------------------------------------------------
* read_callback - handle reads from the input
* stream
*-------------------------------------------------
*/
#define MIN(x, y) ((x) < (y) ? (x) : (y))
static size_t flac_decoder_read_callback(void *userdata, void *buffer, size_t bytes)
{
flac_decoder* decoder = (flac_decoder*)userdata;
uint8_t *dst = buffer;
/* copy from primary buffer first */
uint32_t outputpos = 0;
if (outputpos < bytes && decoder->compressed_offset < decoder->compressed_length)
{
uint32_t bytes_to_copy = MIN(bytes - outputpos, decoder->compressed_length - decoder->compressed_offset);
memcpy(&dst[outputpos], decoder->compressed_start + decoder->compressed_offset, bytes_to_copy);
outputpos += bytes_to_copy;
decoder->compressed_offset += bytes_to_copy;
}
/* once we're out of that, copy from the secondary buffer */
if (outputpos < bytes && decoder->compressed_offset < decoder->compressed_length + decoder->compressed2_length)
{
uint32_t bytes_to_copy = MIN(bytes - outputpos, decoder->compressed2_length - (decoder->compressed_offset - decoder->compressed_length));
memcpy(&dst[outputpos], decoder->compressed2_start + decoder->compressed_offset - decoder->compressed_length, bytes_to_copy);
outputpos += bytes_to_copy;
decoder->compressed_offset += bytes_to_copy;
}
return outputpos;
}
/*-------------------------------------------------
* metadata_callback - handle STREAMINFO metadata
*-------------------------------------------------
*/
static void flac_decoder_metadata_callback(void *userdata, drflac_metadata *metadata)
{
flac_decoder *decoder = userdata;
/* ignore all but STREAMINFO metadata */
if (metadata->type != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO)
return;
/* parse out the data we care about */
decoder->sample_rate = metadata->data.streaminfo.sampleRate;
decoder->bits_per_sample = metadata->data.streaminfo.bitsPerSample;
decoder->channels = metadata->data.streaminfo.channels;
}
/*-------------------------------------------------
* write_callback - handle writes to the output
* stream
*-------------------------------------------------
*/
static void flac_decoder_write_callback(void *userdata, void *buffer, size_t bytes)
{
int sampnum, chan;
int shift, blocksize;
flac_decoder * decoder = (flac_decoder *)userdata;
int16_t *sampbuf = (int16_t *)buffer;
int sampch = channels(decoder);
uint32_t offset = decoder->uncompressed_offset;
uint16_t usample;
/* interleaved case */
shift = decoder->uncompressed_swap ? 8 : 0;
blocksize = bytes / (sampch * sizeof(sampbuf[0]));
if (decoder->uncompressed_start[1] == NULL)
{
int16_t *dest = decoder->uncompressed_start[0] + offset * sampch;
for (sampnum = 0; sampnum < blocksize && offset < decoder->uncompressed_length; sampnum++, offset++)
for (chan = 0; chan < sampch; chan++) {
usample = (uint16_t)*sampbuf++;
*dest++ = (int16_t)((usample << shift) | (usample >> shift));
}
}
/* non-interleaved case */
else
{
for (sampnum = 0; sampnum < blocksize && offset < decoder->uncompressed_length; sampnum++, offset++)
for (chan = 0; chan < sampch; chan++) {
usample = (uint16_t)*sampbuf++;
if (decoder->uncompressed_start[chan] != NULL)
decoder->uncompressed_start[chan][offset] = (int16_t) ((usample << shift) | (usample >> shift));
}
}
decoder->uncompressed_offset = offset;
}
/*-------------------------------------------------
* seek_callback - handle seeks on the output
* stream
*-------------------------------------------------
*/
static drflac_bool32 flac_decoder_seek_callback(void *userdata, int offset, drflac_seek_origin origin)
{
flac_decoder * decoder = (flac_decoder *)userdata;
uint32_t length = decoder->compressed_length + decoder->compressed2_length;
if (origin == drflac_seek_origin_start) {
uint32_t pos = offset;
if (pos <= length) {
decoder->compressed_offset = pos;
return 1;
}
} else if (origin == drflac_seek_origin_current) {
uint32_t pos = decoder->compressed_offset + offset;
if (pos <= length) {
decoder->compressed_offset = pos;
return 1;
}
}
return 0;
}

547
3rdparty/libchdr/src/libchdr_huffman.c vendored Normal file
View File

@ -0,0 +1,547 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
****************************************************************************
huffman.c
Static Huffman compression and decompression helpers.
****************************************************************************
Maximum codelength is officially (alphabetsize - 1). This would be 255 bits
(since we use 1 byte values). However, it is also dependent upon the number
of samples used, as follows:
2 bits -> 3..4 samples
3 bits -> 5..7 samples
4 bits -> 8..12 samples
5 bits -> 13..20 samples
6 bits -> 21..33 samples
7 bits -> 34..54 samples
8 bits -> 55..88 samples
9 bits -> 89..143 samples
10 bits -> 144..232 samples
11 bits -> 233..376 samples
12 bits -> 377..609 samples
13 bits -> 610..986 samples
14 bits -> 987..1596 samples
15 bits -> 1597..2583 samples
16 bits -> 2584..4180 samples -> note that a 4k data size guarantees codelength <= 16 bits
17 bits -> 4181..6764 samples
18 bits -> 6765..10945 samples
19 bits -> 10946..17710 samples
20 bits -> 17711..28656 samples
21 bits -> 28657..46367 samples
22 bits -> 46368..75024 samples
23 bits -> 75025..121392 samples
24 bits -> 121393..196417 samples
25 bits -> 196418..317810 samples
26 bits -> 317811..514228 samples
27 bits -> 514229..832039 samples
28 bits -> 832040..1346268 samples
29 bits -> 1346269..2178308 samples
30 bits -> 2178309..3524577 samples
31 bits -> 3524578..5702886 samples
32 bits -> 5702887..9227464 samples
Looking at it differently, here is where powers of 2 fall into these buckets:
256 samples -> 11 bits max
512 samples -> 12 bits max
1k samples -> 14 bits max
2k samples -> 15 bits max
4k samples -> 16 bits max
8k samples -> 18 bits max
16k samples -> 19 bits max
32k samples -> 21 bits max
64k samples -> 22 bits max
128k samples -> 24 bits max
256k samples -> 25 bits max
512k samples -> 27 bits max
1M samples -> 28 bits max
2M samples -> 29 bits max
4M samples -> 31 bits max
8M samples -> 32 bits max
****************************************************************************
Delta-RLE encoding works as follows:
Starting value is assumed to be 0. All data is encoded as a delta
from the previous value, such that final[i] = final[i - 1] + delta.
Long runs of 0s are RLE-encoded as follows:
0x100 = repeat count of 8
0x101 = repeat count of 9
0x102 = repeat count of 10
0x103 = repeat count of 11
0x104 = repeat count of 12
0x105 = repeat count of 13
0x106 = repeat count of 14
0x107 = repeat count of 15
0x108 = repeat count of 16
0x109 = repeat count of 32
0x10a = repeat count of 64
0x10b = repeat count of 128
0x10c = repeat count of 256
0x10d = repeat count of 512
0x10e = repeat count of 1024
0x10f = repeat count of 2048
Note that repeat counts are reset at the end of a row, so if a 0 run
extends to the end of a row, a large repeat count may be used.
The reason for starting the run counts at 8 is that 0 is expected to
be the most common symbol, and is typically encoded in 1 or 2 bits.
***************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libchdr/huffman.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
/***************************************************************************
* MACROS
***************************************************************************
*/
#define MAKE_LOOKUP(code,bits) (((code) << 5) | ((bits) & 0x1f))
/***************************************************************************
* IMPLEMENTATION
***************************************************************************
*/
/*-------------------------------------------------
* huffman_context_base - create an encoding/
* decoding context
*-------------------------------------------------
*/
struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits)
{
struct huffman_decoder* decoder = NULL;
/* limit to 24 bits */
if (maxbits > 24)
return NULL;
decoder = (struct huffman_decoder*)malloc(sizeof(struct huffman_decoder));
decoder->numcodes = numcodes;
decoder->maxbits = maxbits;
decoder->lookup = (lookup_value*)malloc(sizeof(lookup_value) * (1 << maxbits));
decoder->huffnode = (struct node_t*)malloc(sizeof(struct node_t) * numcodes);
decoder->datahisto = NULL;
decoder->prevdata = 0;
decoder->rleremaining = 0;
return decoder;
}
void delete_huffman_decoder(struct huffman_decoder* decoder)
{
if (decoder != NULL)
{
if (decoder->lookup != NULL)
free(decoder->lookup);
if (decoder->huffnode != NULL)
free(decoder->huffnode);
free(decoder);
}
}
/*-------------------------------------------------
* decode_one - decode a single code from the
* huffman stream
*-------------------------------------------------
*/
uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* bitbuf)
{
/* peek ahead to get maxbits worth of data */
uint32_t bits = bitstream_peek(bitbuf, decoder->maxbits);
/* look it up, then remove the actual number of bits for this code */
lookup_value lookup = decoder->lookup[bits];
bitstream_remove(bitbuf, lookup & 0x1f);
/* return the value */
return lookup >> 5;
}
/*-------------------------------------------------
* import_tree_rle - import an RLE-encoded
* huffman tree from a source data stream
*-------------------------------------------------
*/
enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, struct bitstream* bitbuf)
{
int numbits;
uint32_t curnode;
enum huffman_error error;
/* bits per entry depends on the maxbits */
if (decoder->maxbits >= 16)
numbits = 5;
else if (decoder->maxbits >= 8)
numbits = 4;
else
numbits = 3;
/* loop until we read all the nodes */
for (curnode = 0; curnode < decoder->numcodes; )
{
/* a non-one value is just raw */
int nodebits = bitstream_read(bitbuf, numbits);
if (nodebits != 1)
decoder->huffnode[curnode++].numbits = nodebits;
/* a one value is an escape code */
else
{
/* a double 1 is just a single 1 */
nodebits = bitstream_read(bitbuf, numbits);
if (nodebits == 1)
decoder->huffnode[curnode++].numbits = nodebits;
/* otherwise, we need one for value for the repeat count */
else
{
int repcount = bitstream_read(bitbuf, numbits) + 3;
if (repcount + curnode > decoder->numcodes)
return HUFFERR_INVALID_DATA;
while (repcount--)
decoder->huffnode[curnode++].numbits = nodebits;
}
}
}
/* make sure we ended up with the right number */
if (curnode != decoder->numcodes)
return HUFFERR_INVALID_DATA;
/* assign canonical codes for all nodes based on their code lengths */
error = huffman_assign_canonical_codes(decoder);
if (error != HUFFERR_NONE)
return error;
/* build the lookup table */
huffman_build_lookup_table(decoder);
/* determine final input length and report errors */
return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
}
/*-------------------------------------------------
* import_tree_huffman - import a huffman-encoded
* huffman tree from a source data stream
*-------------------------------------------------
*/
enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder, struct bitstream* bitbuf)
{
int start;
int last = 0;
int count = 0;
int index;
uint32_t curcode;
uint8_t rlefullbits = 0;
uint32_t temp;
enum huffman_error error;
/* start by parsing the lengths for the small tree */
struct huffman_decoder* smallhuff = create_huffman_decoder(24, 6);
smallhuff->huffnode[0].numbits = bitstream_read(bitbuf, 3);
start = bitstream_read(bitbuf, 3) + 1;
for (index = 1; index < 24; index++)
{
if (index < start || count == 7)
smallhuff->huffnode[index].numbits = 0;
else
{
count = bitstream_read(bitbuf, 3);
smallhuff->huffnode[index].numbits = (count == 7) ? 0 : count;
}
}
/* then regenerate the tree */
error = huffman_assign_canonical_codes(smallhuff);
if (error != HUFFERR_NONE)
return error;
huffman_build_lookup_table(smallhuff);
/* determine the maximum length of an RLE count */
temp = decoder->numcodes - 9;
while (temp != 0)
temp >>= 1, rlefullbits++;
/* now process the rest of the data */
for (curcode = 0; curcode < decoder->numcodes; )
{
int value = huffman_decode_one(smallhuff, bitbuf);
if (value != 0)
decoder->huffnode[curcode++].numbits = last = value - 1;
else
{
int count = bitstream_read(bitbuf, 3) + 2;
if (count == 7+2)
count += bitstream_read(bitbuf, rlefullbits);
for ( ; count != 0 && curcode < decoder->numcodes; count--)
decoder->huffnode[curcode++].numbits = last;
}
}
/* make sure we ended up with the right number */
if (curcode != decoder->numcodes)
return HUFFERR_INVALID_DATA;
/* assign canonical codes for all nodes based on their code lengths */
error = huffman_assign_canonical_codes(decoder);
if (error != HUFFERR_NONE)
return error;
/* build the lookup table */
huffman_build_lookup_table(decoder);
/* determine final input length and report errors */
return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
}
/*-------------------------------------------------
* compute_tree_from_histo - common backend for
* computing a tree based on the data histogram
*-------------------------------------------------
*/
enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decoder)
{
uint32_t i;
uint32_t lowerweight;
uint32_t upperweight;
/* compute the number of data items in the histogram */
uint32_t sdatacount = 0;
for (i = 0; i < decoder->numcodes; i++)
sdatacount += decoder->datahisto[i];
/* binary search to achieve the optimum encoding */
lowerweight = 0;
upperweight = sdatacount * 2;
while (1)
{
/* build a tree using the current weight */
uint32_t curweight = (upperweight + lowerweight) / 2;
int curmaxbits = huffman_build_tree(decoder, sdatacount, curweight);
/* apply binary search here */
if (curmaxbits <= decoder->maxbits)
{
lowerweight = curweight;
/* early out if it worked with the raw weights, or if we're done searching */
if (curweight == sdatacount || (upperweight - lowerweight) <= 1)
break;
}
else
upperweight = curweight;
}
/* assign canonical codes for all nodes based on their code lengths */
return huffman_assign_canonical_codes(decoder);
}
/***************************************************************************
* INTERNAL FUNCTIONS
***************************************************************************
*/
/*-------------------------------------------------
* tree_node_compare - compare two tree nodes
* by weight
*-------------------------------------------------
*/
static int huffman_tree_node_compare(const void *item1, const void *item2)
{
const struct node_t *node1 = *(const struct node_t **)item1;
const struct node_t *node2 = *(const struct node_t **)item2;
if (node2->weight != node1->weight)
return node2->weight - node1->weight;
if (node2->bits - node1->bits == 0)
fprintf(stderr, "identical node sort keys, should not happen!\n");
return (int)node1->bits - (int)node2->bits;
}
/*-------------------------------------------------
* build_tree - build a huffman tree based on the
* data distribution
*-------------------------------------------------
*/
int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint32_t totalweight)
{
uint32_t curcode;
int nextalloc;
int listitems = 0;
int maxbits = 0;
/* make a list of all non-zero nodes */
struct node_t** list = (struct node_t**)malloc(sizeof(struct node_t*) * decoder->numcodes * 2);
memset(decoder->huffnode, 0, decoder->numcodes * sizeof(decoder->huffnode[0]));
for (curcode = 0; curcode < decoder->numcodes; curcode++)
if (decoder->datahisto[curcode] != 0)
{
list[listitems++] = &decoder->huffnode[curcode];
decoder->huffnode[curcode].count = decoder->datahisto[curcode];
decoder->huffnode[curcode].bits = curcode;
/* scale the weight by the current effective length, ensuring we don't go to 0 */
decoder->huffnode[curcode].weight = ((uint64_t)decoder->datahisto[curcode]) * ((uint64_t)totalweight) / ((uint64_t)totaldata);
if (decoder->huffnode[curcode].weight == 0)
decoder->huffnode[curcode].weight = 1;
}
#if 0
fprintf(stderr, "Pre-sort:\n");
for (int i = 0; i < listitems; i++) {
fprintf(stderr, "weight: %d code: %d\n", list[i]->m_weight, list[i]->m_bits);
}
#endif
/* sort the list by weight, largest weight first */
qsort(&list[0], listitems, sizeof(list[0]), huffman_tree_node_compare);
#if 0
fprintf(stderr, "Post-sort:\n");
for (int i = 0; i < listitems; i++) {
fprintf(stderr, "weight: %d code: %d\n", list[i]->m_weight, list[i]->m_bits);
}
fprintf(stderr, "===================\n");
#endif
/* now build the tree */
nextalloc = decoder->numcodes;
while (listitems > 1)
{
int curitem;
/* remove lowest two items */
struct node_t* node1 = &(*list[--listitems]);
struct node_t* node0 = &(*list[--listitems]);
/* create new node */
struct node_t* newnode = &decoder->huffnode[nextalloc++];
newnode->parent = NULL;
node0->parent = node1->parent = newnode;
newnode->weight = node0->weight + node1->weight;
/* insert into list at appropriate location */
for (curitem = 0; curitem < listitems; curitem++)
if (newnode->weight > list[curitem]->weight)
{
memmove(&list[curitem+1], &list[curitem], (listitems - curitem) * sizeof(list[0]));
break;
}
list[curitem] = newnode;
listitems++;
}
/* compute the number of bits in each code, and fill in another histogram */
for (curcode = 0; curcode < decoder->numcodes; curcode++)
{
struct node_t *curnode;
struct node_t* node = &decoder->huffnode[curcode];
node->numbits = 0;
node->bits = 0;
/* if we have a non-zero weight, compute the number of bits */
if (node->weight > 0)
{
/* determine the number of bits for this node */
for (curnode = node; curnode->parent != NULL; curnode = curnode->parent)
node->numbits++;
if (node->numbits == 0)
node->numbits = 1;
/* keep track of the max */
maxbits = MAX(maxbits, ((int)node->numbits));
}
}
return maxbits;
}
/*-------------------------------------------------
* assign_canonical_codes - assign canonical codes
* to all the nodes based on the number of bits
* in each
*-------------------------------------------------
*/
enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decoder)
{
uint32_t curcode;
int codelen;
uint32_t curstart = 0;
/* build up a histogram of bit lengths */
uint32_t bithisto[33] = { 0 };
for (curcode = 0; curcode < decoder->numcodes; curcode++)
{
struct node_t* node = &decoder->huffnode[curcode];
if (node->numbits > decoder->maxbits)
return HUFFERR_INTERNAL_INCONSISTENCY;
if (node->numbits <= 32)
bithisto[node->numbits]++;
}
/* for each code length, determine the starting code number */
for (codelen = 32; codelen > 0; codelen--)
{
uint32_t nextstart = (curstart + bithisto[codelen]) >> 1;
if (codelen != 1 && nextstart * 2 != (curstart + bithisto[codelen]))
return HUFFERR_INTERNAL_INCONSISTENCY;
bithisto[codelen] = curstart;
curstart = nextstart;
}
/* now assign canonical codes */
for (curcode = 0; curcode < decoder->numcodes; curcode++)
{
struct node_t* node = &decoder->huffnode[curcode];
if (node->numbits > 0)
node->bits = bithisto[node->numbits]++;
}
return HUFFERR_NONE;
}
/*-------------------------------------------------
* build_lookup_table - build a lookup table for
* fast decoding
*-------------------------------------------------
*/
void huffman_build_lookup_table(struct huffman_decoder* decoder)
{
uint32_t curcode;
/* iterate over all codes */
for (curcode = 0; curcode < decoder->numcodes; curcode++)
{
/* process all nodes which have non-zero bits */
struct node_t* node = &decoder->huffnode[curcode];
if (node->numbits > 0)
{
int shift;
lookup_value *dest;
lookup_value *destend;
/* set up the entry */
lookup_value value = MAKE_LOOKUP(curcode, node->numbits);
/* fill all matching entries */
shift = decoder->maxbits - node->numbits;
dest = &decoder->lookup[node->bits << shift];
destend = &decoder->lookup[((node->bits + 1) << shift) - 1];
while (dest <= destend)
*dest++ = value;
}
}
}

View File

@ -119,6 +119,7 @@ add_subdirectory(3rdparty/fmt/fmt EXCLUDE_FROM_ALL)
add_subdirectory(3rdparty/rapidyaml/rapidyaml EXCLUDE_FROM_ALL)
add_subdirectory(3rdparty/lzma EXCLUDE_FROM_ALL)
add_subdirectory(3rdparty/libchdr EXCLUDE_FROM_ALL)
disable_compiler_warnings_for_target(libchdr)
add_subdirectory(3rdparty/soundtouch EXCLUDE_FROM_ALL)
# rapidyaml includes fast_float as a submodule, saves us pulling it in directly.

View File

@ -1123,7 +1123,7 @@ target_link_libraries(PCSX2_FLAGS INTERFACE
imgui
fmt::fmt
ryml
chdr-static
libchdr
libzip::zip
cpuinfo
zydis

View File

@ -39,7 +39,7 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\xz\xz\src\liblzma\api</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\zlib</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\libpng</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\libchdr\libchdr\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\libchdr\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\cubeb\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\imgui\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\simpleini\include</AdditionalIncludeDirectories>