diff --git a/src/lib/util/chd.cpp b/src/lib/util/chd.cpp index 4130e4a9241..1766ba9898d 100644 --- a/src/lib/util/chd.cpp +++ b/src/lib/util/chd.cpp @@ -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(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)); diff --git a/src/lib/util/chd.h b/src/lib/util/chd.h index 38f86c3f5e9..3d9c54dedda 100644 --- a/src/lib/util/chd.h +++ b/src/lib/util/chd.h @@ -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; diff --git a/src/lib/util/chdcodec.cpp b/src/lib/util/chdcodec.cpp index be48cd55ec9..fa46975285e 100644 --- a/src/lib/util/chdcodec.cpp +++ b/src/lib/util/chdcodec.cpp @@ -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); diff --git a/src/lib/util/flac.cpp b/src/lib/util/flac.cpp index b0d5b9fa565..3492ec0e095 100644 --- a/src/lib/util/flac.cpp +++ b/src/lib/util/flac.cpp @@ -11,6 +11,7 @@ #include "flac.h" #include "ioprocs.h" +#include "multibyte.h" #include #include @@ -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; diff --git a/src/lib/util/multibyte.h b/src/lib/util/multibyte.h index 6664c089506..e61dc8a3ab9 100644 --- a/src/lib/util/multibyte.h +++ b/src/lib/util/multibyte.h @@ -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);