summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/chdcodec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/chdcodec.cpp')
-rw-r--r--src/lib/util/chdcodec.cpp616
1 files changed, 404 insertions, 212 deletions
diff --git a/src/lib/util/chdcodec.cpp b/src/lib/util/chdcodec.cpp
index 71763163a87..c8a1f573bd0 100644
--- a/src/lib/util/chdcodec.cpp
+++ b/src/lib/util/chdcodec.cpp
@@ -2,30 +2,35 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- chdcodec.c
-
Codecs used by the CHD format
***************************************************************************/
-#include <assert.h>
+#include "chdcodec.h"
-#include "chd.h"
-#include "hashing.h"
#include "avhuff.h"
-#include "flac.h"
#include "cdrom.h"
-#include <zlib.h>
-#include "lzma/C/LzmaEnc.h"
+#include "chd.h"
+#include "flac.h"
+#include "hashing.h"
+#include "multibyte.h"
+
#include "lzma/C/LzmaDec.h"
+#include "lzma/C/LzmaEnc.h"
+
+#include <zlib.h>
+#include <zstd.h>
+
#include <new>
+namespace {
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 };
+constexpr uint8_t f_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 };
@@ -35,7 +40,7 @@ static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff
// ======================> chd_zlib_allocator
-// allocation helper clas for zlib
+// allocation helper class for zlib
class chd_zlib_allocator
{
public:
@@ -51,7 +56,8 @@ private:
static voidpf fast_alloc(voidpf opaque, uInt items, uInt size);
static void fast_free(voidpf opaque, voidpf address);
- static const int MAX_ZLIB_ALLOCS = 64;
+ static constexpr int MAX_ZLIB_ALLOCS = 64;
+
uint32_t * m_allocptr[MAX_ZLIB_ALLOCS];
};
@@ -96,6 +102,44 @@ private:
};
+// ======================> chd_zstd_compressor
+
+// Zstandard compressor
+class chd_zstd_compressor : public chd_compressor
+{
+public:
+ // construction/destruction
+ chd_zstd_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy);
+ ~chd_zstd_compressor();
+
+ // core functionality
+ virtual uint32_t compress(const uint8_t *src, uint32_t srclen, uint8_t *dest) override;
+
+private:
+ // internal state
+ ZSTD_CStream * m_stream;
+};
+
+
+// ======================> chd_zstd_decompressor
+
+// Zstandard decompressor
+class chd_zstd_decompressor : public chd_decompressor
+{
+public:
+ // construction/destruction
+ chd_zstd_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy);
+ ~chd_zstd_decompressor();
+
+ // core functionality
+ virtual void decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) override;
+
+private:
+ // internal state
+ ZSTD_DStream * m_stream;
+};
+
+
// ======================> chd_lzma_allocator
// allocation helper clas for zlib
@@ -108,11 +152,11 @@ public:
private:
// internal helpers
- static void *fast_alloc(void *p, size_t size);
- static void fast_free(void *p, void *address);
+ static void *fast_alloc(ISzAllocPtr p, size_t size);
+ static void fast_free(ISzAllocPtr p, void *address);
- static const int MAX_LZMA_ALLOCS = 64;
- uint32_t * m_allocptr[MAX_LZMA_ALLOCS];
+ static constexpr int MAX_LZMA_ALLOCS = 64;
+ uint32_t *m_allocptr[MAX_LZMA_ALLOCS];
};
@@ -287,27 +331,27 @@ private:
// ======================> chd_cd_compressor
-template<class _BaseCompressor, class _SubcodeCompressor>
+template <class BaseCompressor, class SubcodeCompressor>
class chd_cd_compressor : public chd_compressor
{
public:
// construction/destruction
chd_cd_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : chd_compressor(chd, hunkbytes, lossy),
- m_base_compressor(chd, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA, lossy),
- m_subcode_compressor(chd, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA, lossy),
- m_buffer(hunkbytes + (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA)
+ : chd_compressor(chd, hunkbytes, lossy)
+ , m_base_compressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SECTOR_DATA, lossy)
+ , m_subcode_compressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SUBCODE_DATA, lossy)
+ , m_buffer(hunkbytes + (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SUBCODE_DATA)
{
// make sure the CHD's hunk size is an even multiple of the frame size
- if (hunkbytes % CD_FRAME_SIZE != 0)
- throw CHDERR_CODEC_ERROR;
+ if (hunkbytes % cdrom_file::FRAME_SIZE != 0)
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
// core functionality
virtual uint32_t compress(const uint8_t *src, uint32_t srclen, uint8_t *dest) override
{
// determine header bytes
- uint32_t frames = srclen / CD_FRAME_SIZE;
+ uint32_t frames = srclen / cdrom_file::FRAME_SIZE;
uint32_t complen_bytes = (srclen < 65536) ? 2 : 3;
uint32_t ecc_bytes = (frames + 7) / 8;
uint32_t header_bytes = ecc_bytes + complen_bytes;
@@ -318,98 +362,96 @@ public:
// copy audio data followed by subcode data
for (uint32_t framenum = 0; framenum < frames; framenum++)
{
- memcpy(&m_buffer[framenum * CD_MAX_SECTOR_DATA], &src[framenum * CD_FRAME_SIZE], CD_MAX_SECTOR_DATA);
- memcpy(&m_buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], &src[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], CD_MAX_SUBCODE_DATA);
+ memcpy(&m_buffer[framenum * cdrom_file::MAX_SECTOR_DATA], &src[framenum * cdrom_file::FRAME_SIZE], cdrom_file::MAX_SECTOR_DATA);
+ memcpy(&m_buffer[frames * cdrom_file::MAX_SECTOR_DATA + framenum * cdrom_file::MAX_SUBCODE_DATA], &src[framenum * cdrom_file::FRAME_SIZE + cdrom_file::MAX_SECTOR_DATA], cdrom_file::MAX_SUBCODE_DATA);
// clear out ECC data if we can
- uint8_t *sector = &m_buffer[framenum * CD_MAX_SECTOR_DATA];
- if (memcmp(sector, s_cd_sync_header, sizeof(s_cd_sync_header)) == 0 && ecc_verify(sector))
+ uint8_t *sector = &m_buffer[framenum * cdrom_file::MAX_SECTOR_DATA];
+ if (memcmp(sector, f_cd_sync_header, sizeof(f_cd_sync_header)) == 0 && cdrom_file::ecc_verify(sector))
{
dest[framenum / 8] |= 1 << (framenum % 8);
- memset(sector, 0, sizeof(s_cd_sync_header));
- ecc_clear(sector);
+ memset(sector, 0, sizeof(f_cd_sync_header));
+ cdrom_file::ecc_clear(sector);
}
}
// encode the base portion
- uint32_t complen = m_base_compressor.compress(&m_buffer[0], frames * CD_MAX_SECTOR_DATA, &dest[header_bytes]);
+ uint32_t complen = m_base_compressor.compress(&m_buffer[0], frames * cdrom_file::MAX_SECTOR_DATA, &dest[header_bytes]);
if (complen >= srclen)
- throw CHDERR_COMPRESSION_ERROR;
+ 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 * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA, &dest[header_bytes + complen]);
+ 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]);
}
private:
// internal state
- _BaseCompressor m_base_compressor;
- _SubcodeCompressor m_subcode_compressor;
+ BaseCompressor m_base_compressor;
+ SubcodeCompressor m_subcode_compressor;
std::vector<uint8_t> m_buffer;
};
// ======================> chd_cd_decompressor
-template<class _BaseDecompressor, class _SubcodeDecompressor>
+template <class BaseDecompressor, class SubcodeDecompressor>
class chd_cd_decompressor : public chd_decompressor
{
public:
// construction/destruction
chd_cd_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : chd_decompressor(chd, hunkbytes, lossy),
- m_base_decompressor(chd, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA, lossy),
- m_subcode_decompressor(chd, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA, lossy),
- m_buffer(hunkbytes)
+ : chd_decompressor(chd, hunkbytes, lossy)
+ , m_base_decompressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SECTOR_DATA, lossy)
+ , m_subcode_decompressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SUBCODE_DATA, lossy)
+ , m_buffer(hunkbytes)
{
// make sure the CHD's hunk size is an even multiple of the frame size
- if (hunkbytes % CD_FRAME_SIZE != 0)
- throw CHDERR_CODEC_ERROR;
+ if (hunkbytes % cdrom_file::FRAME_SIZE != 0)
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
// core functionality
virtual void decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) override
{
// determine header bytes
- uint32_t frames = destlen / CD_FRAME_SIZE;
+ uint32_t frames = destlen / cdrom_file::FRAME_SIZE;
uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
uint32_t ecc_bytes = (frames + 7) / 8;
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 * CD_MAX_SECTOR_DATA);
- m_subcode_decompressor.decompress(&src[header_bytes + complen_base], complen - complen_base - header_bytes, &m_buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
+ m_base_decompressor.decompress(&src[header_bytes], complen_base, &m_buffer[0], frames * cdrom_file::MAX_SECTOR_DATA);
+ m_subcode_decompressor.decompress(&src[header_bytes + complen_base], complen - complen_base - header_bytes, &m_buffer[frames * cdrom_file::MAX_SECTOR_DATA], frames * cdrom_file::MAX_SUBCODE_DATA);
// reassemble the data
for (uint32_t framenum = 0; framenum < frames; framenum++)
{
- memcpy(&dest[framenum * CD_FRAME_SIZE], &m_buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
- memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &m_buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
+ memcpy(&dest[framenum * cdrom_file::FRAME_SIZE], &m_buffer[framenum * cdrom_file::MAX_SECTOR_DATA], cdrom_file::MAX_SECTOR_DATA);
+ memcpy(&dest[framenum * cdrom_file::FRAME_SIZE + cdrom_file::MAX_SECTOR_DATA], &m_buffer[frames * cdrom_file::MAX_SECTOR_DATA + framenum * cdrom_file::MAX_SUBCODE_DATA], cdrom_file::MAX_SUBCODE_DATA);
// reconstitute the ECC data and sync header
- uint8_t *sector = &dest[framenum * CD_FRAME_SIZE];
+ uint8_t *sector = &dest[framenum * cdrom_file::FRAME_SIZE];
if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
{
- memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
- ecc_generate(sector);
+ memcpy(sector, f_cd_sync_header, sizeof(f_cd_sync_header));
+ cdrom_file::ecc_generate(sector);
}
}
}
private:
// internal state
- _BaseDecompressor m_base_decompressor;
- _SubcodeDecompressor m_subcode_decompressor;
+ BaseDecompressor m_base_decompressor;
+ SubcodeDecompressor m_subcode_decompressor;
std::vector<uint8_t> m_buffer;
};
@@ -446,6 +488,7 @@ public:
chd_avhuff_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy);
// core functionality
+ virtual void process(const uint8_t *src, uint32_t complen) override;
virtual void decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) override;
virtual void configure(int param, void *config) override;
@@ -460,25 +503,67 @@ private:
// CODEC LIST
//**************************************************************************
+// an entry in the list
+struct codec_entry
+{
+ chd_codec_type m_type;
+ bool m_lossy;
+ const char * m_name;
+ chd_compressor::ptr (*m_construct_compressor)(chd_file &, uint32_t, bool);
+ chd_decompressor::ptr (*m_construct_decompressor)(chd_file &, uint32_t, bool);
+
+ template <class CompressorClass>
+ static chd_compressor::ptr construct_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
+ {
+ return std::make_unique<CompressorClass>(chd, hunkbytes, lossy);
+ }
+
+ template <class DecompressorClass>
+ static chd_decompressor::ptr construct_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
+ {
+ return std::make_unique<DecompressorClass>(chd, hunkbytes, lossy);
+ }
+};
+
+
// static list of available known codecs
-const chd_codec_list::codec_entry chd_codec_list::s_codec_list[] =
+const codec_entry f_codec_list[] =
{
// general codecs
- { CHD_CODEC_ZLIB, false, "Deflate", &chd_codec_list::construct_compressor<chd_zlib_compressor>, &chd_codec_list::construct_decompressor<chd_zlib_decompressor> },
- { CHD_CODEC_LZMA, false, "LZMA", &chd_codec_list::construct_compressor<chd_lzma_compressor>, &chd_codec_list::construct_decompressor<chd_lzma_decompressor> },
- { CHD_CODEC_HUFFMAN, false, "Huffman", &chd_codec_list::construct_compressor<chd_huffman_compressor>, &chd_codec_list::construct_decompressor<chd_huffman_decompressor> },
- { CHD_CODEC_FLAC, false, "FLAC", &chd_codec_list::construct_compressor<chd_flac_compressor>, &chd_codec_list::construct_decompressor<chd_flac_decompressor> },
+ { CHD_CODEC_ZLIB, false, "Deflate", &codec_entry::construct_compressor<chd_zlib_compressor>, &codec_entry::construct_decompressor<chd_zlib_decompressor> },
+ { CHD_CODEC_ZSTD, false, "Zstandard", &codec_entry::construct_compressor<chd_zstd_compressor>, &codec_entry::construct_decompressor<chd_zstd_decompressor> },
+ { CHD_CODEC_LZMA, false, "LZMA", &codec_entry::construct_compressor<chd_lzma_compressor>, &codec_entry::construct_decompressor<chd_lzma_decompressor> },
+ { CHD_CODEC_HUFFMAN, false, "Huffman", &codec_entry::construct_compressor<chd_huffman_compressor>, &codec_entry::construct_decompressor<chd_huffman_decompressor> },
+ { CHD_CODEC_FLAC, false, "FLAC", &codec_entry::construct_compressor<chd_flac_compressor>, &codec_entry::construct_decompressor<chd_flac_decompressor> },
// general codecs with CD frontend
- { CHD_CODEC_CD_ZLIB, false, "CD Deflate", &chd_codec_list::construct_compressor<chd_cd_compressor<chd_zlib_compressor, chd_zlib_compressor> >, &chd_codec_list::construct_decompressor<chd_cd_decompressor<chd_zlib_decompressor, chd_zlib_decompressor> > },
- { CHD_CODEC_CD_LZMA, false, "CD LZMA", &chd_codec_list::construct_compressor<chd_cd_compressor<chd_lzma_compressor, chd_zlib_compressor> >, &chd_codec_list::construct_decompressor<chd_cd_decompressor<chd_lzma_decompressor, chd_zlib_decompressor> > },
- { CHD_CODEC_CD_FLAC, false, "CD FLAC", &chd_codec_list::construct_compressor<chd_cd_flac_compressor>, &chd_codec_list::construct_decompressor<chd_cd_flac_decompressor> },
+ { CHD_CODEC_CD_ZLIB, false, "CD Deflate", &codec_entry::construct_compressor<chd_cd_compressor<chd_zlib_compressor, chd_zlib_compressor> >, &codec_entry::construct_decompressor<chd_cd_decompressor<chd_zlib_decompressor, chd_zlib_decompressor> > },
+ { CHD_CODEC_CD_ZSTD, false, "CD Zstandard", &codec_entry::construct_compressor<chd_cd_compressor<chd_zstd_compressor, chd_zstd_compressor> >, &codec_entry::construct_decompressor<chd_cd_decompressor<chd_zstd_decompressor, chd_zstd_decompressor> > },
+ { CHD_CODEC_CD_LZMA, false, "CD LZMA", &codec_entry::construct_compressor<chd_cd_compressor<chd_lzma_compressor, chd_zlib_compressor> >, &codec_entry::construct_decompressor<chd_cd_decompressor<chd_lzma_decompressor, chd_zlib_decompressor> > },
+ { CHD_CODEC_CD_FLAC, false, "CD FLAC", &codec_entry::construct_compressor<chd_cd_flac_compressor>, &codec_entry::construct_decompressor<chd_cd_flac_decompressor> },
// A/V codecs
- { CHD_CODEC_AVHUFF, false, "A/V Huffman", &chd_codec_list::construct_compressor<chd_avhuff_compressor>, &chd_codec_list::construct_decompressor<chd_avhuff_decompressor> },
+ { CHD_CODEC_AVHUFF, false, "A/V Huffman", &codec_entry::construct_compressor<chd_avhuff_compressor>, &codec_entry::construct_decompressor<chd_avhuff_decompressor> },
};
+//-------------------------------------------------
+// find_in_list - create a new compressor
+// instance of the given type
+//-------------------------------------------------
+
+const codec_entry *find_in_list(chd_codec_type type) noexcept
+{
+ // find in the list and construct the class
+ for (auto & elem : f_codec_list)
+ if (elem.m_type == type)
+ return &elem;
+ return nullptr;
+}
+
+} // anonymous namespace
+
+
//**************************************************************************
// CHD CODEC
@@ -489,9 +574,9 @@ const chd_codec_list::codec_entry chd_codec_list::s_codec_list[] =
//-------------------------------------------------
chd_codec::chd_codec(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : m_chd(chd),
- m_hunkbytes(hunkbytes),
- m_lossy(lossy)
+ : m_chd(chd)
+ , m_hunkbytes(hunkbytes)
+ , m_lossy(lossy)
{
}
@@ -512,7 +597,7 @@ chd_codec::~chd_codec()
void chd_codec::configure(int param, void *config)
{
// if not overridden, it is always a failure
- throw CHDERR_INVALID_PARAMETER;
+ throw std::error_condition(std::errc::invalid_argument);
}
@@ -521,10 +606,6 @@ void chd_codec::configure(int param, void *config)
// CHD COMPRESSOR
//**************************************************************************
-//-------------------------------------------------
-// chd_compressor - constructor
-//-------------------------------------------------
-
chd_compressor::chd_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
: chd_codec(chd, hunkbytes, lossy)
{
@@ -536,15 +617,16 @@ chd_compressor::chd_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
// CHD DECOMPRESSOR
//**************************************************************************
-//-------------------------------------------------
-// chd_decompressor - constructor
-//-------------------------------------------------
-
chd_decompressor::chd_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
: chd_codec(chd, hunkbytes, lossy)
{
}
+void chd_decompressor::process(const uint8_t *src, uint32_t complen)
+{
+ throw std::error_condition(chd_file::error::UNSUPPORTED_FORMAT);
+}
+
//**************************************************************************
@@ -556,11 +638,11 @@ chd_decompressor::chd_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy
// instance of the given type
//-------------------------------------------------
-chd_compressor *chd_codec_list::new_compressor(chd_codec_type type, chd_file &chd)
+chd_compressor::ptr chd_codec_list::new_compressor(chd_codec_type type, chd_file &chd)
{
// find in the list and construct the class
- const codec_entry *entry = find_in_list(type);
- return (entry == nullptr) ? nullptr : (*entry->m_construct_compressor)(chd, chd.hunk_bytes(), entry->m_lossy);
+ codec_entry const *const entry = find_in_list(type);
+ return entry ? (*entry->m_construct_compressor)(chd, chd.hunk_bytes(), entry->m_lossy) : nullptr;
}
@@ -569,39 +651,36 @@ chd_compressor *chd_codec_list::new_compressor(chd_codec_type type, chd_file &ch
// instance of the given type
//-------------------------------------------------
-chd_decompressor *chd_codec_list::new_decompressor(chd_codec_type type, chd_file &chd)
+chd_decompressor::ptr chd_codec_list::new_decompressor(chd_codec_type type, chd_file &chd)
{
// find in the list and construct the class
const codec_entry *entry = find_in_list(type);
- return (entry == nullptr) ? nullptr : (*entry->m_construct_decompressor)(chd, chd.hunk_bytes(), entry->m_lossy);
+ return entry ? (*entry->m_construct_decompressor)(chd, chd.hunk_bytes(), entry->m_lossy) : nullptr;
}
//-------------------------------------------------
-// codec_name - return the name of the given
-// codec
+// codec_exists - determine whether a codec type
+// corresponds to a supported codec
//-------------------------------------------------
-const char *chd_codec_list::codec_name(chd_codec_type type)
+bool chd_codec_list::codec_exists(chd_codec_type type) noexcept
{
// find in the list and construct the class
- const codec_entry *entry = find_in_list(type);
- return (entry == nullptr) ? nullptr : entry->m_name;
+ return bool(find_in_list(type));
}
//-------------------------------------------------
-// find_in_list - create a new compressor
-// instance of the given type
+// codec_name - return the name of the given
+// codec
//-------------------------------------------------
-const chd_codec_list::codec_entry *chd_codec_list::find_in_list(chd_codec_type type)
+const char *chd_codec_list::codec_name(chd_codec_type type) noexcept
{
// find in the list and construct the class
- for (auto & elem : s_codec_list)
- if (elem.m_type == type)
- return &elem;
- return nullptr;
+ const codec_entry *entry = find_in_list(type);
+ return entry ? entry->m_name : nullptr;
}
@@ -615,25 +694,24 @@ const chd_codec_list::codec_entry *chd_codec_list::find_in_list(chd_codec_type t
//-------------------------------------------------
chd_compressor_group::chd_compressor_group(chd_file &chd, uint32_t compressor_list[4])
- : m_hunkbytes(chd.hunk_bytes()),
- m_compress_test(m_hunkbytes)
+ : m_hunkbytes(chd.hunk_bytes())
+ , m_compress_test(m_hunkbytes)
#if CHDCODEC_VERIFY_COMPRESSION
- ,m_decompressed(m_hunkbytes)
+ , m_decompressed(m_hunkbytes)
#endif
{
// verify the compression types and initialize the codecs
- for (int codecnum = 0; codecnum < ARRAY_LENGTH(m_compressor); codecnum++)
+ for (int codecnum = 0; codecnum < std::size(m_compressor); codecnum++)
{
- m_compressor[codecnum] = nullptr;
if (compressor_list[codecnum] != CHD_CODEC_NONE)
{
m_compressor[codecnum] = chd_codec_list::new_compressor(compressor_list[codecnum], chd);
- if (m_compressor[codecnum] == nullptr)
- throw CHDERR_UNKNOWN_COMPRESSION;
+ if (!m_compressor[codecnum])
+ throw std::error_condition(chd_file::error::UNKNOWN_COMPRESSION);
#if CHDCODEC_VERIFY_COMPRESSION
m_decompressor[codecnum] = chd_codec_list::new_decompressor(compressor_list[codecnum], chd);
- if (m_decompressor[codecnum] == nullptr)
- throw CHDERR_UNKNOWN_COMPRESSION;
+ if (!m_decompressor[codecnum])
+ throw std::error_condition(chd_file::error::UNKNOWN_COMPRESSION);
#endif
}
}
@@ -646,9 +724,7 @@ chd_compressor_group::chd_compressor_group(chd_file &chd, uint32_t compressor_li
chd_compressor_group::~chd_compressor_group()
{
- // delete the codecs and the test buffer
- for (auto & elem : m_compressor)
- delete elem;
+ // codecs and test buffer deleted automatically
}
@@ -663,8 +739,8 @@ int8_t chd_compressor_group::find_best_compressor(const uint8_t *src, uint8_t *c
// determine best compression technique
complen = m_hunkbytes;
int8_t compression = -1;
- for (int codecnum = 0; codecnum < ARRAY_LENGTH(m_compressor); codecnum++)
- if (m_compressor[codecnum] != nullptr)
+ for (int codecnum = 0; codecnum < std::size(m_compressor); codecnum++)
+ if (m_compressor[codecnum])
{
// attempt to compress, swallowing errors
try
@@ -702,7 +778,9 @@ printf(" codec%d=%d bytes \n", codecnum, compbytes);
memcpy(compressed, &m_compress_test[0], compbytes);
}
}
- catch (...) { }
+ catch (...)
+ {
+ }
}
// if the best is none, copy it over
@@ -729,7 +807,7 @@ chd_zlib_allocator::chd_zlib_allocator()
//-------------------------------------------------
-// ~chd_zlib_allocator - constructor
+// ~chd_zlib_allocator - destructor
//-------------------------------------------------
chd_zlib_allocator::~chd_zlib_allocator()
@@ -760,7 +838,7 @@ void chd_zlib_allocator::install(z_stream &stream)
voidpf chd_zlib_allocator::fast_alloc(voidpf opaque, uInt items, uInt size)
{
- chd_zlib_allocator *codec = reinterpret_cast<chd_zlib_allocator *>(opaque);
+ auto *codec = reinterpret_cast<chd_zlib_allocator *>(opaque);
// compute the size, rounding to the nearest 1k
size = (size * items + 0x3ff) & ~0x3ff;
@@ -778,7 +856,7 @@ voidpf chd_zlib_allocator::fast_alloc(voidpf opaque, uInt items, uInt size)
}
// alloc a new one and put it into the list
- uint32_t *ptr = reinterpret_cast<uint32_t *>(new uint8_t[size + sizeof(uint32_t)]);
+ auto *ptr = reinterpret_cast<uint32_t *>(new uint8_t[size + sizeof(uint32_t)]);
for (int scan = 0; scan < MAX_ZLIB_ALLOCS; scan++)
if (codec->m_allocptr[scan] == nullptr)
{
@@ -799,7 +877,7 @@ voidpf chd_zlib_allocator::fast_alloc(voidpf opaque, uInt items, uInt size)
void chd_zlib_allocator::fast_free(voidpf opaque, voidpf address)
{
- chd_zlib_allocator *codec = reinterpret_cast<chd_zlib_allocator *>(opaque);
+ auto *codec = reinterpret_cast<chd_zlib_allocator *>(opaque);
// find the hunk
uint32_t *ptr = reinterpret_cast<uint32_t *>(address) - 1;
@@ -835,7 +913,7 @@ chd_zlib_compressor::chd_zlib_compressor(chd_file &chd, uint32_t hunkbytes, bool
if (zerr == Z_MEM_ERROR)
throw std::bad_alloc();
else if (zerr != Z_OK)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
@@ -855,7 +933,7 @@ chd_zlib_compressor::~chd_zlib_compressor()
uint32_t chd_zlib_compressor::compress(const uint8_t *src, uint32_t srclen, uint8_t *dest)
{
- // reset the decompressor
+ // reset the compressor
m_deflater.next_in = const_cast<Bytef *>(src);
m_deflater.avail_in = srclen;
m_deflater.total_in = 0;
@@ -864,14 +942,14 @@ uint32_t chd_zlib_compressor::compress(const uint8_t *src, uint32_t srclen, uint
m_deflater.total_out = 0;
int zerr = deflateReset(&m_deflater);
if (zerr != Z_OK)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// do it
zerr = deflate(&m_deflater, Z_FINISH);
// if we ended up with more data than we started with, return an error
if (zerr != Z_STREAM_END || m_deflater.total_out >= srclen)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// otherwise, return the length
return m_deflater.total_out;
@@ -900,7 +978,7 @@ chd_zlib_decompressor::chd_zlib_decompressor(chd_file &chd, uint32_t hunkbytes,
if (zerr == Z_MEM_ERROR)
throw std::bad_alloc();
else if (zerr != Z_OK)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
@@ -930,14 +1008,139 @@ void chd_zlib_decompressor::decompress(const uint8_t *src, uint32_t complen, uin
m_inflater.total_out = 0;
int zerr = inflateReset(&m_inflater);
if (zerr != Z_OK)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// do it
zerr = inflate(&m_inflater, Z_FINISH);
if (zerr != Z_STREAM_END)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
if (m_inflater.total_out != destlen)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
+}
+
+
+
+//**************************************************************************
+// ZSTANDARD COMPRESSOR
+//**************************************************************************
+
+//-------------------------------------------------
+// chd_zstd_compressor - constructor
+//-------------------------------------------------
+
+chd_zstd_compressor::chd_zstd_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
+ : chd_compressor(chd, hunkbytes, lossy)
+ , m_stream(nullptr)
+{
+ // initialize the stream
+ m_stream = ZSTD_createCStream();
+
+ // convert errors
+ if (!m_stream)
+ throw std::bad_alloc();
+}
+
+
+//-------------------------------------------------
+// ~chd_zstd_compressor - destructor
+//-------------------------------------------------
+
+chd_zstd_compressor::~chd_zstd_compressor()
+{
+ ZSTD_freeCStream(m_stream);
+}
+
+
+//-------------------------------------------------
+// compress - compress data using the Zstandard
+// codec
+//-------------------------------------------------
+
+uint32_t chd_zstd_compressor::compress(const uint8_t *src, uint32_t srclen, uint8_t *dest)
+{
+ // reset the compressor
+ auto result = ZSTD_initCStream(m_stream, ZSTD_maxCLevel());
+ if (ZSTD_isError(result))
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
+
+ // do it
+ ZSTD_inBuffer input{ src, srclen, 0 };
+ ZSTD_outBuffer output = { dest, srclen, 0 };
+ while (output.pos < output.size)
+ {
+ result = ZSTD_compressStream2(m_stream, &output, &input, ZSTD_e_end);
+ if (ZSTD_isError(result))
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
+ else if (!result)
+ break;
+ }
+
+ // if we ended up with more data than we started with, return an error
+ if (output.pos == output.size)
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
+
+ // otherwise, return the length
+ return output.pos;
+}
+
+
+
+//**************************************************************************
+// ZSTANDARD DECOMPRESSOR
+//**************************************************************************
+
+//-------------------------------------------------
+// chd_zstd_compressor - constructor
+//-------------------------------------------------
+
+chd_zstd_decompressor::chd_zstd_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
+ : chd_decompressor(chd, hunkbytes, lossy)
+ , m_stream(nullptr)
+{
+ // initialize the stream
+ m_stream = ZSTD_createDStream();
+
+ // convert errors
+ if (!m_stream)
+ throw std::bad_alloc();
+}
+
+
+//-------------------------------------------------
+// ~chd_zstd_decompressor - destructor
+//-------------------------------------------------
+
+chd_zstd_decompressor::~chd_zstd_decompressor()
+{
+ ZSTD_freeDStream(m_stream);
+}
+
+
+//-------------------------------------------------
+// decompress - decompress data using the
+// Zstandard codec
+//-------------------------------------------------
+
+void chd_zstd_decompressor::decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
+{
+ // reset the decompressor
+ auto result = ZSTD_initDStream(m_stream);
+ if (ZSTD_isError(result))
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
+
+ // do it
+ ZSTD_inBuffer input{ src, complen, 0 };
+ ZSTD_outBuffer output = { dest, destlen, 0 };
+ while ((input.pos < input.size) && (output.pos < output.size))
+ {
+ result = ZSTD_decompressStream(m_stream, &output, &input);
+ if (ZSTD_isError(result))
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
+ }
+
+ // ensure the expected amount of output was generated
+ if (output.pos != output.size)
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
}
@@ -978,9 +1181,9 @@ chd_lzma_allocator::~chd_lzma_allocator()
// allocates and frees memory frequently
//-------------------------------------------------
-void *chd_lzma_allocator::fast_alloc(void *p, size_t size)
+void *chd_lzma_allocator::fast_alloc(ISzAllocPtr p, size_t size)
{
- chd_lzma_allocator *codec = reinterpret_cast<chd_lzma_allocator *>(p);
+ auto *const codec = static_cast<chd_lzma_allocator *>(const_cast<ISzAlloc *>(p));
// compute the size, rounding to the nearest 1k
size = (size + 0x3ff) & ~0x3ff;
@@ -998,7 +1201,7 @@ void *chd_lzma_allocator::fast_alloc(void *p, size_t size)
}
// alloc a new one and put it into the list
- uint32_t *ptr = reinterpret_cast<uint32_t *>(new uint8_t[size + sizeof(uint32_t)]);
+ auto *ptr = reinterpret_cast<uint32_t *>(new uint8_t[size + sizeof(uint32_t)]);
for (int scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
if (codec->m_allocptr[scan] == nullptr)
{
@@ -1017,12 +1220,12 @@ void *chd_lzma_allocator::fast_alloc(void *p, size_t size)
// allocates and frees memory frequently
//-------------------------------------------------
-void chd_lzma_allocator::fast_free(void *p, void *address)
+void chd_lzma_allocator::fast_free(ISzAllocPtr p, void *address)
{
if (address == nullptr)
return;
- chd_lzma_allocator *codec = reinterpret_cast<chd_lzma_allocator *>(p);
+ auto *const codec = static_cast<chd_lzma_allocator *>(const_cast<ISzAlloc *>(p));
// find the hunk
uint32_t *ptr = reinterpret_cast<uint32_t *>(address) - 1;
@@ -1071,20 +1274,20 @@ uint32_t chd_lzma_compressor::compress(const uint8_t *src, uint32_t srclen, uint
// allocate the encoder
CLzmaEncHandle encoder = LzmaEnc_Create(&m_allocator);
if (encoder == nullptr)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
try
{
// configure the encoder
SRes res = LzmaEnc_SetProps(encoder, &m_props);
if (res != SZ_OK)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// run it
SizeT complen = srclen;
res = LzmaEnc_MemEncode(encoder, dest, &complen, src, srclen, 0, nullptr, &m_allocator, &m_allocator);
if (res != SZ_OK)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// clean up
LzmaEnc_Destroy(encoder, &m_allocator, &m_allocator);
@@ -1107,7 +1310,7 @@ uint32_t chd_lzma_compressor::compress(const uint8_t *src, uint32_t srclen, uint
void chd_lzma_compressor::configure_properties(CLzmaEncProps &props, uint32_t hunkbytes)
{
LzmaEncProps_Init(&props);
- props.level = 9;
+ props.level = 8;
props.reduceSize = hunkbytes;
LzmaEncProps_Normalize(&props);
}
@@ -1140,24 +1343,24 @@ chd_lzma_decompressor::chd_lzma_decompressor(chd_file &chd, uint32_t hunkbytes,
// convert to decoder properties
CLzmaEncHandle enc = LzmaEnc_Create(&m_allocator);
if (!enc)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
{
LzmaEnc_Destroy(enc, &m_allocator, &m_allocator);
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
}
Byte decoder_props[LZMA_PROPS_SIZE];
SizeT props_size = sizeof(decoder_props);
if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
{
LzmaEnc_Destroy(enc, &m_allocator, &m_allocator);
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
}
LzmaEnc_Destroy(enc, &m_allocator, &m_allocator);
// do memory allocations
if (LzmaDec_Allocate(&m_decoder, decoder_props, LZMA_PROPS_SIZE, &m_allocator) != SZ_OK)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
}
@@ -1188,7 +1391,7 @@ void chd_lzma_decompressor::decompress(const uint8_t *src, uint32_t complen, uin
ELzmaStatus status;
SRes res = LzmaDec_DecodeToBuf(&m_decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
}
@@ -1216,7 +1419,7 @@ uint32_t chd_huffman_compressor::compress(const uint8_t *src, uint32_t srclen, u
{
uint32_t complen;
if (m_encoder.encode(src, srclen, dest, srclen, complen) != HUFFERR_NONE)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
return complen;
}
@@ -1244,7 +1447,7 @@ chd_huffman_decompressor::chd_huffman_decompressor(chd_file &chd, uint32_t hunkb
void chd_huffman_decompressor::decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
if (m_decoder.decode(src, complen, dest, destlen) != HUFFERR_NONE)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
}
@@ -1282,19 +1485,19 @@ uint32_t chd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, uint
// reset and encode big-endian
m_encoder.reset(dest + 1, hunkbytes() - 1);
if (!m_encoder.encode_interleaved(reinterpret_cast<const int16_t *>(src), srclen / 4, !m_big_endian))
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
uint32_t complen_be = m_encoder.finish();
// reset and encode little-endian
m_encoder.reset(dest + 1, hunkbytes() - 1);
if (!m_encoder.encode_interleaved(reinterpret_cast<const int16_t *>(src), srclen / 4, m_big_endian))
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
uint32_t complen_le = m_encoder.finish();
// pick the best one and add a byte
uint32_t complen = std::min(complen_le, complen_be);
if (complen + 1 >= hunkbytes())
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// if big-endian was better, re-do it
dest[0] = 'L';
@@ -1303,7 +1506,7 @@ uint32_t chd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, uint
dest[0] = 'B';
m_encoder.reset(dest + 1, hunkbytes() - 1);
if (!m_encoder.encode_interleaved(reinterpret_cast<const int16_t *>(src), srclen / 4, !m_big_endian))
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
m_encoder.finish();
}
return complen + 1;
@@ -1358,13 +1561,13 @@ void chd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen, uin
else if (src[0] == 'B')
swap_endian = !m_big_endian;
else
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// reset and decode
if (!m_decoder.reset(44100, 2, chd_flac_compressor::blocksize(destlen), src + 1, complen - 1))
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
if (!m_decoder.decode_interleaved(reinterpret_cast<int16_t *>(dest), destlen / 4, swap_endian))
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// finish up
m_decoder.finish();
@@ -1381,12 +1584,12 @@ void chd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen, uin
//-------------------------------------------------
chd_cd_flac_compressor::chd_cd_flac_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : chd_compressor(chd, hunkbytes, lossy),
- m_buffer(hunkbytes)
+ : chd_compressor(chd, hunkbytes, lossy)
+ , m_buffer(hunkbytes)
{
// make sure the CHD's hunk size is an even multiple of the frame size
- if (hunkbytes % CD_FRAME_SIZE != 0)
- throw CHDERR_CODEC_ERROR;
+ if (hunkbytes % cdrom_file::FRAME_SIZE != 0)
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
// determine whether we want native or swapped samples
uint16_t native_endian = 0;
@@ -1396,7 +1599,7 @@ chd_cd_flac_compressor::chd_cd_flac_compressor(chd_file &chd, uint32_t hunkbytes
// configure the encoder
m_encoder.set_sample_rate(44100);
m_encoder.set_num_channels(2);
- m_encoder.set_block_size(blocksize((hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA));
+ m_encoder.set_block_size(blocksize((hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SECTOR_DATA));
m_encoder.set_strip_metadata(true);
// initialize the deflater
@@ -1409,7 +1612,7 @@ chd_cd_flac_compressor::chd_cd_flac_compressor(chd_file &chd, uint32_t hunkbytes
if (zerr == Z_MEM_ERROR)
throw std::bad_alloc();
else if (zerr != Z_OK)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
@@ -1431,32 +1634,32 @@ chd_cd_flac_compressor::~chd_cd_flac_compressor()
uint32_t chd_cd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, uint8_t *dest)
{
// copy audio data followed by subcode data
- uint32_t frames = hunkbytes() / CD_FRAME_SIZE;
+ uint32_t frames = hunkbytes() / cdrom_file::FRAME_SIZE;
for (uint32_t framenum = 0; framenum < frames; framenum++)
{
- memcpy(&m_buffer[framenum * CD_MAX_SECTOR_DATA], &src[framenum * CD_FRAME_SIZE], CD_MAX_SECTOR_DATA);
- memcpy(&m_buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], &src[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], CD_MAX_SUBCODE_DATA);
+ memcpy(&m_buffer[framenum * cdrom_file::MAX_SECTOR_DATA], &src[framenum * cdrom_file::FRAME_SIZE], cdrom_file::MAX_SECTOR_DATA);
+ memcpy(&m_buffer[frames * cdrom_file::MAX_SECTOR_DATA + framenum * cdrom_file::MAX_SUBCODE_DATA], &src[framenum * cdrom_file::FRAME_SIZE + cdrom_file::MAX_SECTOR_DATA], cdrom_file::MAX_SUBCODE_DATA);
}
// reset and encode the audio portion
m_encoder.reset(dest, hunkbytes());
uint8_t *buffer = &m_buffer[0];
- if (!m_encoder.encode_interleaved(reinterpret_cast<int16_t *>(buffer), frames * CD_MAX_SECTOR_DATA/4, m_swap_endian))
- throw CHDERR_COMPRESSION_ERROR;
+ if (!m_encoder.encode_interleaved(reinterpret_cast<int16_t *>(buffer), frames * cdrom_file::MAX_SECTOR_DATA/4, m_swap_endian))
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// finish up
uint32_t complen = m_encoder.finish();
// deflate the subcode data
- m_deflater.next_in = const_cast<Bytef *>(&m_buffer[frames * CD_MAX_SECTOR_DATA]);
- m_deflater.avail_in = frames * CD_MAX_SUBCODE_DATA;
+ m_deflater.next_in = const_cast<Bytef *>(&m_buffer[frames * cdrom_file::MAX_SECTOR_DATA]);
+ m_deflater.avail_in = frames * cdrom_file::MAX_SUBCODE_DATA;
m_deflater.total_in = 0;
m_deflater.next_out = &dest[complen];
m_deflater.avail_out = hunkbytes() - complen;
m_deflater.total_out = 0;
int zerr = deflateReset(&m_deflater);
if (zerr != Z_OK)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// do it
zerr = deflate(&m_deflater, Z_FINISH);
@@ -1464,7 +1667,7 @@ uint32_t chd_cd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, u
// if we ended up with more data than we started with, return an error
complen += m_deflater.total_out;
if (zerr != Z_STREAM_END || complen >= srclen)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
return complen;
}
@@ -1484,7 +1687,7 @@ uint32_t chd_cd_flac_compressor::blocksize(uint32_t bytes)
{
// for CDs it seems that CD_MAX_SECTOR_DATA is the right target
uint32_t blocksize = bytes / 4;
- while (blocksize > CD_MAX_SECTOR_DATA)
+ while (blocksize > cdrom_file::MAX_SECTOR_DATA)
blocksize /= 2;
return blocksize;
}
@@ -1510,12 +1713,12 @@ uint32_t chd_cd_flac_compressor::blocksize(uint32_t bytes)
*/
chd_cd_flac_decompressor::chd_cd_flac_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : chd_decompressor(chd, hunkbytes, lossy),
- m_buffer(hunkbytes)
+ : chd_decompressor(chd, hunkbytes, lossy)
+ , m_buffer(hunkbytes)
{
// make sure the CHD's hunk size is an even multiple of the frame size
- if (hunkbytes % CD_FRAME_SIZE != 0)
- throw CHDERR_CODEC_ERROR;
+ if (hunkbytes % cdrom_file::FRAME_SIZE != 0)
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
// determine whether we want native or swapped samples
uint16_t native_endian = 0;
@@ -1532,7 +1735,7 @@ chd_cd_flac_decompressor::chd_cd_flac_decompressor(chd_file &chd, uint32_t hunkb
if (zerr == Z_MEM_ERROR)
throw std::bad_alloc();
else if (zerr != Z_OK)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
/**
@@ -1567,37 +1770,37 @@ chd_cd_flac_decompressor::~chd_cd_flac_decompressor()
void chd_cd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
// reset and decode
- uint32_t frames = destlen / CD_FRAME_SIZE;
- if (!m_decoder.reset(44100, 2, chd_cd_flac_compressor::blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
- throw CHDERR_DECOMPRESSION_ERROR;
+ uint32_t frames = destlen / cdrom_file::FRAME_SIZE;
+ if (!m_decoder.reset(44100, 2, chd_cd_flac_compressor::blocksize(frames * cdrom_file::MAX_SECTOR_DATA), src, complen))
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
uint8_t *buffer = &m_buffer[0];
- if (!m_decoder.decode_interleaved(reinterpret_cast<int16_t *>(buffer), frames * CD_MAX_SECTOR_DATA/4, m_swap_endian))
- throw CHDERR_DECOMPRESSION_ERROR;
+ if (!m_decoder.decode_interleaved(reinterpret_cast<int16_t *>(buffer), frames * cdrom_file::MAX_SECTOR_DATA/4, m_swap_endian))
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// inflate the subcode data
uint32_t offset = m_decoder.finish();
m_inflater.next_in = const_cast<Bytef *>(src + offset);
m_inflater.avail_in = complen - offset;
m_inflater.total_in = 0;
- m_inflater.next_out = &m_buffer[frames * CD_MAX_SECTOR_DATA];
- m_inflater.avail_out = frames * CD_MAX_SUBCODE_DATA;
+ m_inflater.next_out = &m_buffer[frames * cdrom_file::MAX_SECTOR_DATA];
+ m_inflater.avail_out = frames * cdrom_file::MAX_SUBCODE_DATA;
m_inflater.total_out = 0;
int zerr = inflateReset(&m_inflater);
if (zerr != Z_OK)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// do it
zerr = inflate(&m_inflater, Z_FINISH);
if (zerr != Z_STREAM_END)
- throw CHDERR_DECOMPRESSION_ERROR;
- if (m_inflater.total_out != frames * CD_MAX_SUBCODE_DATA)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
+ if (m_inflater.total_out != frames * cdrom_file::MAX_SUBCODE_DATA)
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// reassemble the data
for (uint32_t framenum = 0; framenum < frames; framenum++)
{
- memcpy(&dest[framenum * CD_FRAME_SIZE], &m_buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
- memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &m_buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
+ memcpy(&dest[framenum * cdrom_file::FRAME_SIZE], &m_buffer[framenum * cdrom_file::MAX_SECTOR_DATA], cdrom_file::MAX_SECTOR_DATA);
+ memcpy(&dest[framenum * cdrom_file::FRAME_SIZE + cdrom_file::MAX_SECTOR_DATA], &m_buffer[frames * cdrom_file::MAX_SECTOR_DATA + framenum * cdrom_file::MAX_SUBCODE_DATA], cdrom_file::MAX_SUBCODE_DATA);
}
}
@@ -1620,15 +1823,15 @@ void chd_cd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen,
*/
chd_avhuff_compressor::chd_avhuff_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : chd_compressor(chd, hunkbytes, lossy),
- m_postinit(false)
+ : chd_compressor(chd, hunkbytes, lossy)
+ , m_postinit(false)
{
try
{
// attempt to do a post-init now
postinit();
}
- catch (chd_error &)
+ catch (std::error_condition const &)
{
// if we're creating a new CHD, it won't work but that's ok
}
@@ -1665,14 +1868,14 @@ uint32_t chd_avhuff_compressor::compress(const uint8_t *src, uint32_t srclen, ui
int size = avhuff_encoder::raw_data_size(src);
while (size < srclen)
if (src[size++] != 0)
- throw CHDERR_INVALID_DATA;
+ throw std::error_condition(chd_file::error::INVALID_DATA);
}
// encode the audio and video
uint32_t complen;
avhuff_error averr = m_encoder.encode_data(src, dest, complen);
if (averr != AVHERR_NONE || complen > srclen)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
return complen;
}
@@ -1693,21 +1896,21 @@ void chd_avhuff_compressor::postinit()
{
// get the metadata
std::string metadata;
- chd_error err = chd().read_metadata(AV_METADATA_TAG, 0, metadata);
- if (err != CHDERR_NONE)
+ std::error_condition err = chd().read_metadata(AV_METADATA_TAG, 0, metadata);
+ if (err)
throw err;
// extract the info
int fps, fpsfrac, width, height, interlaced, channels, rate;
if (sscanf(metadata.c_str(), AV_METADATA_FORMAT, &fps, &fpsfrac, &width, &height, &interlaced, &channels, &rate) != 7)
- throw CHDERR_INVALID_METADATA;
+ throw std::error_condition(chd_file::error::INVALID_METADATA);
// compute the bytes per frame
uint32_t fps_times_1million = fps * 1000000 + fpsfrac;
uint32_t max_samples_per_frame = (uint64_t(rate) * 1000000 + fps_times_1million - 1) / fps_times_1million;
uint32_t bytes_per_frame = 12 + channels * max_samples_per_frame * 2 + width * height * 2;
if (bytes_per_frame > hunkbytes())
- throw CHDERR_INVALID_METADATA;
+ throw std::error_condition(chd_file::error::INVALID_METADATA);
// done with post-init
m_postinit = true;
@@ -1736,36 +1939,25 @@ chd_avhuff_decompressor::chd_avhuff_decompressor(chd_file &chd, uint32_t hunkbyt
{
}
-/**
- * @fn void chd_avhuff_decompressor::decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
- *
- * @brief -------------------------------------------------
- * decompress - decompress data using the A/V codec
- * -------------------------------------------------.
- *
- * @exception CHDERR_DECOMPRESSION_ERROR Thrown when a chderr decompression error error
- * condition occurs.
- *
- * @param src Source for the.
- * @param complen The complen.
- * @param [in,out] dest If non-null, destination for the.
- * @param destlen The destlen.
- */
+void chd_avhuff_decompressor::process(const uint8_t *src, uint32_t complen)
+{
+ // decode the audio and video
+ avhuff_error averr = m_decoder.decode_data(src, complen, nullptr);
+ if (averr != AVHERR_NONE)
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
+}
void chd_avhuff_decompressor::decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
// decode the audio and video
avhuff_error averr = m_decoder.decode_data(src, complen, dest);
if (averr != AVHERR_NONE)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// pad short frames with 0
- if (dest != nullptr)
- {
- int size = avhuff_encoder::raw_data_size(dest);
- if (size < destlen)
- memset(dest + size, 0, destlen - size);
- }
+ auto const size = avhuff_encoder::raw_data_size(dest);
+ if (size < destlen)
+ memset(dest + size, 0, destlen - size);
}
/**
@@ -1786,9 +1978,9 @@ void chd_avhuff_decompressor::configure(int param, void *config)
{
// if we're getting the decompression configuration, apply it now
if (param == AVHUFF_CODEC_DECOMPRESS_CONFIG)
- m_decoder.configure(*reinterpret_cast<avhuff_decompress_config *>(config));
+ m_decoder.configure(*reinterpret_cast<avhuff_decoder::config const *>(config));
// anything else is invalid
else
- throw CHDERR_INVALID_PARAMETER;
+ throw std::error_condition(std::errc::invalid_argument);
}