chd.cpp, chdcodec.cpp, flac.cpp: Use multibyte.h functions

* multibyte.h: Add functions for reading and writing 48-bit values
This commit is contained in:
AJR 2023-09-17 19:59:30 -04:00
parent 5077dcbe1c
commit 94ff3857e2
5 changed files with 160 additions and 133 deletions

View File

@ -16,6 +16,7 @@
#include "coretmpl.h"
#include "flac.h"
#include "hashing.h"
#include "multibyte.h"
#include "eminline.h"
@ -128,36 +129,6 @@ struct chd_file::metadata_hash
// INLINE FUNCTIONS
//**************************************************************************
//-------------------------------------------------
// be_read - extract a big-endian number from
// a byte buffer
//-------------------------------------------------
inline uint64_t chd_file::be_read(const uint8_t *base, int numbytes) const
{
uint64_t result = 0;
while (numbytes--)
result = (result << 8) | *base++;
return result;
}
//-------------------------------------------------
// be_write - write a big-endian number to a byte
// buffer
//-------------------------------------------------
inline void chd_file::be_write(uint8_t *base, uint64_t value, int numbytes)
{
base += numbytes;
while (numbytes--)
{
*--base = value;
value >>= 8;
}
}
//-------------------------------------------------
// be_read_sha1 - fetch a sha1_t from a data
// stream in bigendian order
@ -471,7 +442,7 @@ std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compr
{
case V34_MAP_ENTRY_TYPE_COMPRESSED:
compressor = CHD_CODEC_ZLIB;
compbytes = be_read(&rawmap[12], 2) + (rawmap[14] << 16);
compbytes = get_u16be(&rawmap[12]) + (rawmap[14] << 16);
break;
case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
@ -503,7 +474,7 @@ std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compr
// uncompressed case
if (!compressed())
{
if (be_read(&rawmap[0], 4) == 0)
if (get_u32be(&rawmap[0]) == 0)
{
compressor = CHD_CODEC_PARENT;
compbytes = 0;
@ -524,7 +495,7 @@ std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compr
case COMPRESSION_TYPE_2:
case COMPRESSION_TYPE_3:
compressor = m_compression[rawmap[0]];
compbytes = be_read(&rawmap[1], 3);
compbytes = get_u24be(&rawmap[1]);
break;
case COMPRESSION_NONE:
@ -917,12 +888,12 @@ std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer)
case 3:
case 4:
rawmap = &m_rawmap[16 * hunknum];
blockoffs = be_read(&rawmap[0], 8);
blockcrc = be_read(&rawmap[8], 4);
blockoffs = get_u64be(&rawmap[0]);
blockcrc = get_u32be(&rawmap[8]);
switch (rawmap[15] & V34_MAP_ENTRY_FLAG_TYPE_MASK)
{
case V34_MAP_ENTRY_TYPE_COMPRESSED:
blocklen = be_read(&rawmap[12], 2) + (rawmap[14] << 16);
blocklen = get_u16be(&rawmap[12]) + (rawmap[14] << 16);
file_read(blockoffs, &m_compressed[0], blocklen);
m_decompressor[0]->decompress(&m_compressed[0], blocklen, dest, m_hunkbytes);
if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && dest != nullptr && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
@ -936,7 +907,7 @@ std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer)
return std::error_condition();
case V34_MAP_ENTRY_TYPE_MINI:
be_write(dest, blockoffs, 8);
put_u64be(dest, blockoffs);
for (uint32_t bytes = 8; bytes < m_hunkbytes; bytes++)
dest[bytes] = dest[bytes - 8];
if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
@ -960,7 +931,7 @@ std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer)
// uncompressed case
if (!compressed())
{
blockoffs = uint64_t(be_read(rawmap, 4)) * uint64_t(m_hunkbytes);
blockoffs = mulu_32x32(get_u32be(rawmap), m_hunkbytes);
if (blockoffs != 0)
file_read(blockoffs, dest, m_hunkbytes);
else if (m_parent_missing)
@ -973,9 +944,9 @@ std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer)
}
// compressed case
blocklen = be_read(&rawmap[1], 3);
blockoffs = be_read(&rawmap[4], 6);
blockcrc = be_read(&rawmap[10], 2);
blocklen = get_u24be(&rawmap[1]);
blockoffs = get_u48be(&rawmap[4]);
blockcrc = get_u16be(&rawmap[10]);
switch (rawmap[0])
{
case COMPRESSION_TYPE_0:
@ -1059,7 +1030,7 @@ std::error_condition chd_file::write_hunk(uint32_t hunknum, const void *buffer)
// see if we have allocated the space on disk for this hunk
uint8_t *rawmap = &m_rawmap[hunknum * 4];
uint32_t rawentry = be_read(rawmap, 4);
uint32_t rawentry = get_u32be(rawmap);
// if not, allocate one now
if (rawentry == 0)
@ -1082,7 +1053,7 @@ std::error_condition chd_file::write_hunk(uint32_t hunknum, const void *buffer)
rawentry = file_append(buffer, m_hunkbytes, m_hunkbytes) / m_hunkbytes;
// write the map entry back
be_write(rawmap, rawentry, 4);
put_u32be(rawmap, rawentry);
file_write(m_mapoffset + hunknum * 4, rawmap, 4);
// update the cached hunk if we just wrote it
@ -1443,7 +1414,7 @@ std::error_condition chd_file::write_metadata(chd_metadata_tag metatag, uint32_t
if (inputlen != metaentry.length)
{
uint8_t length[3];
be_write(length, inputlen, 3);
put_u24be(length, inputlen);
file_write(metaentry.offset + 5, length, sizeof(length));
}
@ -1461,10 +1432,10 @@ std::error_condition chd_file::write_metadata(chd_metadata_tag metatag, uint32_t
{
// now build us a new entry
uint8_t raw_meta_header[METADATA_HEADER_SIZE];
be_write(&raw_meta_header[0], metatag, 4);
put_u32be(&raw_meta_header[0], metatag);
raw_meta_header[4] = flags;
be_write(&raw_meta_header[5], (inputlen & 0x00ffffff) | (flags << 24), 3);
be_write(&raw_meta_header[8], 0, 8);
put_u24be(&raw_meta_header[5], inputlen & 0x00ffffff);
put_u64be(&raw_meta_header[8], 0);
// append the new header, then the data
uint64_t offset = file_append(raw_meta_header, sizeof(raw_meta_header));
@ -1603,7 +1574,7 @@ util::sha1_t chd_file::compute_overall_sha1(util::sha1_t rawsha1)
// create an entry for this metadata and add it
metadata_hash hashentry;
be_write(hashentry.tag, metaentry.metatag, 4);
put_u32be(hashentry.tag, metaentry.metatag);
hashentry.sha1 = util::sha1_creator::simple(&filedata[0], metaentry.length);
hasharray.push_back(hashentry);
}
@ -1768,22 +1739,22 @@ uint32_t chd_file::guess_unitbytes()
void chd_file::parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1)
{
// verify header length
if (be_read(&rawheader[8], 4) != V3_HEADER_SIZE)
if (get_u32be(&rawheader[8]) != V3_HEADER_SIZE)
throw std::error_condition(error::INVALID_FILE);
// extract core info
m_logicalbytes = be_read(&rawheader[28], 8);
m_logicalbytes = get_u64be(&rawheader[28]);
m_mapoffset = 120;
m_metaoffset = be_read(&rawheader[36], 8);
m_hunkbytes = be_read(&rawheader[76], 4);
m_hunkcount = be_read(&rawheader[24], 4);
m_metaoffset = get_u64be(&rawheader[36]);
m_hunkbytes = get_u32be(&rawheader[76]);
m_hunkcount = get_u32be(&rawheader[24]);
// extract parent SHA-1
uint32_t flags = be_read(&rawheader[16], 4);
uint32_t flags = get_u32be(&rawheader[16]);
m_allow_writes = (flags & 2) == 0;
// determine compression
switch (be_read(&rawheader[20], 4))
switch (get_u32be(&rawheader[20]))
{
case 0: m_compression[0] = CHD_CODEC_NONE; break;
case 1: m_compression[0] = CHD_CODEC_ZLIB; break;
@ -1831,22 +1802,22 @@ void chd_file::parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1)
void chd_file::parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1)
{
// verify header length
if (be_read(&rawheader[8], 4) != V4_HEADER_SIZE)
if (get_u32be(&rawheader[8]) != V4_HEADER_SIZE)
throw std::error_condition(error::INVALID_FILE);
// extract core info
m_logicalbytes = be_read(&rawheader[28], 8);
m_logicalbytes = get_u64be(&rawheader[28]);
m_mapoffset = 108;
m_metaoffset = be_read(&rawheader[36], 8);
m_hunkbytes = be_read(&rawheader[44], 4);
m_hunkcount = be_read(&rawheader[24], 4);
m_metaoffset = get_u64be(&rawheader[36]);
m_hunkbytes = get_u32be(&rawheader[44]);
m_hunkcount = get_u32be(&rawheader[24]);
// extract parent SHA-1
uint32_t flags = be_read(&rawheader[16], 4);
uint32_t flags = get_u32be(&rawheader[16]);
m_allow_writes = (flags & 2) == 0;
// determine compression
switch (be_read(&rawheader[20], 4))
switch (get_u32be(&rawheader[20]))
{
case 0: m_compression[0] = CHD_CODEC_NONE; break;
case 1: m_compression[0] = CHD_CODEC_ZLIB; break;
@ -1891,23 +1862,23 @@ void chd_file::parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1)
void chd_file::parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1)
{
// verify header length
if (be_read(&rawheader[8], 4) != V5_HEADER_SIZE)
if (get_u32be(&rawheader[8]) != V5_HEADER_SIZE)
throw std::error_condition(error::INVALID_FILE);
// extract core info
m_logicalbytes = be_read(&rawheader[32], 8);
m_mapoffset = be_read(&rawheader[40], 8);
m_metaoffset = be_read(&rawheader[48], 8);
m_hunkbytes = be_read(&rawheader[56], 4);
m_logicalbytes = get_u64be(&rawheader[32]);
m_mapoffset = get_u64be(&rawheader[40]);
m_metaoffset = get_u64be(&rawheader[48]);
m_hunkbytes = get_u32be(&rawheader[56]);
m_hunkcount = (m_logicalbytes + m_hunkbytes - 1) / m_hunkbytes;
m_unitbytes = be_read(&rawheader[60], 4);
m_unitbytes = get_u32be(&rawheader[60]);
m_unitcount = (m_logicalbytes + m_unitbytes - 1) / m_unitbytes;
// determine compression
m_compression[0] = be_read(&rawheader[16], 4);
m_compression[1] = be_read(&rawheader[20], 4);
m_compression[2] = be_read(&rawheader[24], 4);
m_compression[3] = be_read(&rawheader[28], 4);
m_compression[0] = get_u32be(&rawheader[16]);
m_compression[1] = get_u32be(&rawheader[20]);
m_compression[2] = get_u32be(&rawheader[24]);
m_compression[3] = get_u32be(&rawheader[28]);
m_allow_writes = !compressed();
@ -1961,14 +1932,14 @@ std::error_condition chd_file::compress_v5_map()
uint32_t max_complen = 0;
uint8_t lastcomp = 0;
int count = 0;
for (int hunknum = 0; hunknum < m_hunkcount; hunknum++)
for (uint32_t hunknum = 0; hunknum < m_hunkcount; hunknum++)
{
uint8_t curcomp = m_rawmap[hunknum * 12 + 0];
// promote self block references to more compact forms
if (curcomp == COMPRESSION_SELF)
{
uint32_t refhunk = be_read(&m_rawmap[hunknum * 12 + 4], 6);
uint32_t refhunk = get_u48be(&m_rawmap[hunknum * 12 + 4]);
if (refhunk == last_self)
curcomp = COMPRESSION_SELF_0;
else if (refhunk == last_self + 1)
@ -1981,8 +1952,8 @@ std::error_condition chd_file::compress_v5_map()
// promote parent block references to more compact forms
else if (curcomp == COMPRESSION_PARENT)
{
uint32_t refunit = be_read(&m_rawmap[hunknum * 12 + 4], 6);
if (refunit == (uint64_t(hunknum) * uint64_t(m_hunkbytes)) / m_unitbytes)
uint32_t refunit = get_u48be(&m_rawmap[hunknum * 12 + 4]);
if (refunit == mulu_32x32(hunknum, m_hunkbytes) / m_unitbytes)
curcomp = COMPRESSION_PARENT_SELF;
else if (refunit == last_parent)
curcomp = COMPRESSION_PARENT_0;
@ -1995,7 +1966,7 @@ std::error_condition chd_file::compress_v5_map()
// track maximum compressed length
else //if (curcomp >= COMPRESSION_TYPE_0 && curcomp <= COMPRESSION_TYPE_3)
max_complen = std::max(max_complen, uint32_t(be_read(&m_rawmap[hunknum * 12 + 1], 3)));
max_complen = std::max<uint32_t>(max_complen, get_u24be(&m_rawmap[hunknum * 12 + 1]));
// track repeats
if (curcomp == lastcomp)
@ -2053,12 +2024,12 @@ std::error_condition chd_file::compress_v5_map()
count = 0;
uint8_t *src = &compression_rle[0];
uint64_t firstoffs = 0;
for (int hunknum = 0; hunknum < m_hunkcount; hunknum++)
for (uint32_t hunknum = 0; hunknum < m_hunkcount; hunknum++)
{
uint8_t *rawmap = &m_rawmap[hunknum * 12];
uint32_t length = be_read(&rawmap[1], 3);
uint64_t offset = be_read(&rawmap[4], 6);
uint16_t crc = be_read(&rawmap[10], 2);
uint32_t length = get_u24be(&rawmap[1]);
uint64_t offset = get_u48be(&rawmap[4]);
uint16_t crc = get_u16be(&rawmap[10]);
// if no count remaining, fetch the next entry
if (count == 0)
@ -2116,9 +2087,9 @@ std::error_condition chd_file::compress_v5_map()
// write the map header
uint32_t complen = bitbuf.flush();
assert(!bitbuf.overflow());
be_write(&compressed[0], complen, 4);
be_write(&compressed[4], firstoffs, 6);
be_write(&compressed[10], mapcrc, 2);
put_u32be(&compressed[0], complen);
put_u48be(&compressed[4], firstoffs);
put_u16be(&compressed[10], mapcrc);
compressed[12] = lengthbits;
compressed[13] = selfbits;
compressed[14] = parentbits;
@ -2129,7 +2100,7 @@ std::error_condition chd_file::compress_v5_map()
// then write the map offset
uint8_t rawbuf[sizeof(uint64_t)];
be_write(rawbuf, m_mapoffset, 8);
put_u64be(rawbuf, m_mapoffset);
file_write(m_mapoffset_offset, rawbuf, sizeof(rawbuf));
return std::error_condition();
}
@ -2162,9 +2133,9 @@ void chd_file::decompress_v5_map()
// read the reader
uint8_t rawbuf[16];
file_read(m_mapoffset, rawbuf, sizeof(rawbuf));
uint32_t const mapbytes = be_read(&rawbuf[0], 4);
uint64_t const firstoffs = be_read(&rawbuf[4], 6);
util::crc16_t const mapcrc = be_read(&rawbuf[10], 2);
uint32_t const mapbytes = get_u32be(&rawbuf[0]);
uint64_t const firstoffs = get_u48be(&rawbuf[4]);
util::crc16_t const mapcrc = get_u16be(&rawbuf[10]);
uint8_t const lengthbits = rawbuf[12];
uint8_t const selfbits = rawbuf[13];
uint8_t const parentbits = rawbuf[14];
@ -2181,7 +2152,7 @@ void chd_file::decompress_v5_map()
throw std::error_condition(error::DECOMPRESSION_ERROR);
uint8_t lastcomp = 0;
int repcount = 0;
for (int hunknum = 0; hunknum < m_hunkcount; hunknum++)
for (uint32_t hunknum = 0; hunknum < m_hunkcount; hunknum++)
{
uint8_t *rawmap = &m_rawmap[hunknum * 12];
if (repcount > 0)
@ -2202,7 +2173,7 @@ void chd_file::decompress_v5_map()
uint64_t curoffset = firstoffs;
uint32_t last_self = 0;
uint64_t last_parent = 0;
for (int hunknum = 0; hunknum < m_hunkcount; hunknum++)
for (uint32_t hunknum = 0; hunknum < m_hunkcount; hunknum++)
{
uint8_t *rawmap = &m_rawmap[hunknum * 12];
uint64_t offset = curoffset;
@ -2244,7 +2215,7 @@ void chd_file::decompress_v5_map()
case COMPRESSION_PARENT_SELF:
rawmap[0] = COMPRESSION_PARENT;
last_parent = offset = (uint64_t(hunknum) * uint64_t(m_hunkbytes)) / m_unitbytes;
last_parent = offset = mulu_32x32(hunknum, m_hunkbytes) / m_unitbytes;
break;
case COMPRESSION_PARENT_1:
@ -2255,9 +2226,9 @@ void chd_file::decompress_v5_map()
offset = last_parent;
break;
}
be_write(&rawmap[1], length, 3);
be_write(&rawmap[4], offset, 6);
be_write(&rawmap[10], crc, 2);
put_u24be(&rawmap[1], length);
put_u48be(&rawmap[4], offset);
put_u16be(&rawmap[10], crc);
}
// verify the final CRC
@ -2316,17 +2287,17 @@ std::error_condition chd_file::create_common()
// create our V5 header
uint8_t rawheader[V5_HEADER_SIZE];
memcpy(&rawheader[0], "MComprHD", 8);
be_write(&rawheader[8], V5_HEADER_SIZE, 4);
be_write(&rawheader[12], m_version, 4);
be_write(&rawheader[16], m_compression[0], 4);
be_write(&rawheader[20], m_compression[1], 4);
be_write(&rawheader[24], m_compression[2], 4);
be_write(&rawheader[28], m_compression[3], 4);
be_write(&rawheader[32], m_logicalbytes, 8);
be_write(&rawheader[40], compressed() ? 0 : V5_HEADER_SIZE, 8);
be_write(&rawheader[48], m_metaoffset, 8);
be_write(&rawheader[56], m_hunkbytes, 4);
be_write(&rawheader[60], m_unitbytes, 4);
put_u32be(&rawheader[8], V5_HEADER_SIZE);
put_u32be(&rawheader[12], m_version);
put_u32be(&rawheader[16], m_compression[0]);
put_u32be(&rawheader[20], m_compression[1]);
put_u32be(&rawheader[24], m_compression[2]);
put_u32be(&rawheader[28], m_compression[3]);
put_u64be(&rawheader[32], m_logicalbytes);
put_u64be(&rawheader[40], compressed() ? 0 : V5_HEADER_SIZE);
put_u64be(&rawheader[48], m_metaoffset);
put_u32be(&rawheader[56], m_hunkbytes);
put_u32be(&rawheader[60], m_unitbytes);
be_write_sha1(&rawheader[64], util::sha1_t::null);
be_write_sha1(&rawheader[84], util::sha1_t::null);
be_write_sha1(&rawheader[104], (m_parent != nullptr) ? m_parent->sha1() : util::sha1_t::null);
@ -2413,7 +2384,7 @@ std::error_condition chd_file::open_common(bool writeable)
if (memcmp(rawheader, "MComprHD", 8) != 0)
throw std::error_condition(error::INVALID_FILE);
m_version = be_read(&rawheader[12], 4);
m_version = get_u32be(&rawheader[12]);
// read the header if we support it
util::sha1_t parentsha1 = util::sha1_t::null;
@ -2562,9 +2533,9 @@ void chd_file::hunk_write_compressed(uint32_t hunknum, int8_t compression, const
// update the map entry
uint8_t *rawmap = &m_rawmap[hunknum * 12];
rawmap[0] = (compression == -1) ? COMPRESSION_NONE : compression;
be_write(&rawmap[1], complength, 3);
be_write(&rawmap[4], offset, 6);
be_write(&rawmap[10], crc16, 2);
put_u24be(&rawmap[1], complength);
put_u48be(&rawmap[4], offset);
put_u16be(&rawmap[10], crc16);
}
/**
@ -2593,9 +2564,9 @@ void chd_file::hunk_copy_from_self(uint32_t hunknum, uint32_t otherhunk)
// update the map entry
uint8_t *rawmap = &m_rawmap[hunknum * 12];
rawmap[0] = COMPRESSION_SELF;
be_write(&rawmap[1], 0, 3);
be_write(&rawmap[4], otherhunk, 6);
be_write(&rawmap[10], 0, 2);
put_u24be(&rawmap[1], 0);
put_u48be(&rawmap[4], otherhunk);
put_u16be(&rawmap[10], 0);
}
/**
@ -2617,9 +2588,9 @@ void chd_file::hunk_copy_from_parent(uint32_t hunknum, uint64_t parentunit)
// update the map entry
uint8_t *rawmap = &m_rawmap[hunknum * 12];
rawmap[0] = COMPRESSION_PARENT;
be_write(&rawmap[1], 0, 3);
be_write(&rawmap[4], parentunit, 6);
be_write(&rawmap[10], 0, 2);
put_u24be(&rawmap[1], 0);
put_u48be(&rawmap[4], parentunit);
put_u16be(&rawmap[10], 0);
}
/**
@ -2659,10 +2630,10 @@ bool chd_file::metadata_find(chd_metadata_tag metatag, int32_t metaindex, metada
file_read(metaentry.offset, raw_meta_header, sizeof(raw_meta_header));
// extract the data
metaentry.metatag = be_read(&raw_meta_header[0], 4);
metaentry.metatag = get_u32be(&raw_meta_header[0]);
metaentry.flags = raw_meta_header[4];
metaentry.length = be_read(&raw_meta_header[5], 3);
metaentry.next = be_read(&raw_meta_header[8], 8);
metaentry.length = get_u24be(&raw_meta_header[5]);
metaentry.next = get_u64be(&raw_meta_header[8]);
// if we got a match, proceed
if (metatag == CHDMETATAG_WILDCARD || metaentry.metatag == metatag)
@ -2706,7 +2677,7 @@ void chd_file::metadata_set_previous_next(uint64_t prevoffset, uint64_t nextoffs
// create a big-endian version
uint8_t rawbuf[sizeof(uint64_t)];
be_write(rawbuf, nextoffset, 8);
put_u64be(rawbuf, nextoffset);
// write to the header and update our local copy
file_write(offset, rawbuf, sizeof(rawbuf));

View File

@ -367,8 +367,6 @@ private:
struct metadata_hash;
// inline helpers
uint64_t be_read(const uint8_t *base, int numbytes) const;
void be_write(uint8_t *base, uint64_t value, int numbytes);
util::sha1_t be_read_sha1(const uint8_t *base) const;
void be_write_sha1(uint8_t *base, util::sha1_t value);
void file_read(uint64_t offset, void *dest, uint32_t length) const;

View File

@ -15,6 +15,7 @@
#include "chd.h"
#include "flac.h"
#include "hashing.h"
#include "multibyte.h"
#include "lzma/C/LzmaDec.h"
#include "lzma/C/LzmaEnc.h"
@ -343,10 +344,10 @@ public:
throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// write compressed length
dest[ecc_bytes + 0] = complen >> ((complen_bytes - 1) * 8);
dest[ecc_bytes + 1] = complen >> ((complen_bytes - 2) * 8);
if (complen_bytes > 2)
dest[ecc_bytes + 2] = complen >> ((complen_bytes - 3) * 8);
put_u24be(&dest[ecc_bytes], complen);
else
put_u16be(&dest[ecc_bytes], complen);
// encode the subcode
return header_bytes + complen + m_subcode_compressor.compress(&m_buffer[frames * cdrom_file::MAX_SECTOR_DATA], frames * cdrom_file::MAX_SUBCODE_DATA, &dest[header_bytes + complen]);
@ -388,9 +389,7 @@ public:
uint32_t header_bytes = ecc_bytes + complen_bytes;
// extract compressed length of base
uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
if (complen_bytes > 2)
complen_base = (complen_base << 8) | src[ecc_bytes + 2];
uint32_t complen_base = (complen_bytes > 2) ? get_u24be(&src[ecc_bytes]) : get_u16be(&src[ecc_bytes]);
// reset and decode
m_base_decompressor.decompress(&src[header_bytes], complen_base, &m_buffer[0], frames * cdrom_file::MAX_SECTOR_DATA);

View File

@ -11,6 +11,7 @@
#include "flac.h"
#include "ioprocs.h"
#include "multibyte.h"
#include <algorithm>
#include <cassert>
@ -256,7 +257,7 @@ FLAC__StreamEncoderWriteStatus flac_encoder::write_callback(const FLAC__byte buf
// if we haven't hit the end of metadata, process a new piece
assert(bytes - offset >= 4);
m_found_audio = ((buffer[offset] & 0x80) != 0);
m_ignore_bytes = (buffer[offset + 1] << 16) | (buffer[offset + 2] << 8) | buffer[offset + 3];
m_ignore_bytes = get_u24be(&buffer[offset + 1]);
offset += 4;
}
else
@ -415,11 +416,9 @@ bool flac_decoder::reset(uint32_t sample_rate, uint8_t num_channels, uint32_t bl
// +2A: start of stream data
};
memcpy(m_custom_header, s_header_template, sizeof(s_header_template));
m_custom_header[0x08] = m_custom_header[0x0a] = block_size >> 8;
m_custom_header[0x09] = m_custom_header[0x0b] = block_size & 0xff;
m_custom_header[0x12] = sample_rate >> 12;
m_custom_header[0x13] = sample_rate >> 4;
m_custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1);
put_u16be(&m_custom_header[0x08], block_size);
put_u16be(&m_custom_header[0x0a], block_size);
put_u24be(&m_custom_header[0x12], (sample_rate << 4) | ((num_channels - 1) << 1));
// configure the header ahead of the provided buffer
m_file = nullptr;

View File

@ -43,6 +43,16 @@ inline constexpr u32 get_u32be(const u8 *const buf) noexcept
| ((const u32)buf[3] << 0);
}
inline constexpr u64 get_u48be(const u8 *const buf) noexcept
{
return ((const u64)buf[0] << 40)
| ((const u64)buf[1] << 36)
| ((const u64)buf[2] << 24)
| ((const u64)buf[3] << 16)
| ((const u64)buf[4] << 8)
| ((const u64)buf[5] << 0);
}
inline constexpr u64 get_u64be(const u8 *const buf) noexcept
{
return ((const u64)buf[0] << 56)
@ -76,6 +86,16 @@ inline void put_u32be(u8 *buf, const u32 data) noexcept
buf[3] = data >> 0;
}
inline void put_u48be(u8 *buf, const u64 data) noexcept
{
buf[0] = data >> 40;
buf[1] = data >> 36;
buf[2] = data >> 24;
buf[3] = data >> 16;
buf[4] = data >> 8;
buf[5] = data >> 0;
}
inline void put_u64be(u8 *buf, const u64 data) noexcept
{
buf[0] = data >> 56;
@ -107,6 +127,11 @@ inline constexpr s32 get_s32be(const u8 *const buf) noexcept
return get_u32be(buf);
}
inline constexpr s64 get_s48be(const u8 *const buf) noexcept
{
return util::sext(get_u48be(buf), 48);
}
inline constexpr s64 get_s64be(const u8 *const buf) noexcept
{
return get_u64be(buf);
@ -127,6 +152,11 @@ inline void put_s32be(u8 *buf, const s32 data) noexcept
put_u32be(buf, data);
}
inline void put_s48be(u8 *buf, const s64 data) noexcept
{
put_u48be(buf, data);
}
inline void put_s64be(u8 *buf, const s64 data) noexcept
{
put_u64be(buf, data);
@ -157,6 +187,16 @@ inline constexpr u32 get_u32le(const u8 *const buf) noexcept
| ((const u32)buf[3] << 24);
}
inline constexpr u64 get_u48le(const u8 *const buf) noexcept
{
return ((const u64)buf[0] << 0)
| ((const u64)buf[1] << 8)
| ((const u64)buf[2] << 16)
| ((const u64)buf[3] << 24)
| ((const u64)buf[4] << 32)
| ((const u64)buf[5] << 40);
}
inline constexpr u64 get_u64le(const u8 *const buf) noexcept
{
return ((const u64)buf[0] << 0)
@ -190,6 +230,16 @@ inline void put_u32le(u8 *buf, const u32 data) noexcept
buf[3] = data >> 24;
}
inline void put_u48le(u8 *buf, const u64 data) noexcept
{
buf[0] = data >> 0;
buf[1] = data >> 8;
buf[2] = data >> 16;
buf[3] = data >> 24;
buf[4] = data >> 32;
buf[5] = data >> 40;
}
inline void put_u64le(u8 *buf, const u64 data) noexcept
{
buf[0] = data >> 0;
@ -221,6 +271,11 @@ inline constexpr s32 get_s32le(const u8 *const buf) noexcept
return get_u32le(buf);
}
inline constexpr s64 get_s48le(const u8 *const buf) noexcept
{
return util::sext(get_u48le(buf), 48);
}
inline constexpr s64 get_s64le(const u8 *const buf) noexcept
{
return get_u64le(buf);
@ -241,6 +296,11 @@ inline void put_s32le(u8 *buf, const s32 data) noexcept
put_u32le(buf, data);
}
inline void put_s48le(u8 *buf, const s64 data) noexcept
{
put_u48le(buf, data);
}
inline void put_s64le(u8 *buf, const s64 data) noexcept
{
put_u64le(buf, data);