summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/chd.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/chd.h')
-rw-r--r--src/lib/util/chd.h274
1 files changed, 136 insertions, 138 deletions
diff --git a/src/lib/util/chd.h b/src/lib/util/chd.h
index 705967d3dda..8d3e639438b 100644
--- a/src/lib/util/chd.h
+++ b/src/lib/util/chd.h
@@ -7,18 +7,22 @@
MAME Compressed Hunks of Data file format
***************************************************************************/
-
-#ifndef MAME_UTIL_CHD_H
-#define MAME_UTIL_CHD_H
+#ifndef MAME_LIB_UTIL_CHD_H
+#define MAME_LIB_UTIL_CHD_H
#pragma once
-#include "osdcore.h"
-#include <string>
-#include "corefile.h"
-#include "hashing.h"
#include "chdcodec.h"
+#include "hashing.h"
+#include "ioprocs.h"
+
+#include "osdcore.h"
+
#include <atomic>
+#include <string>
+#include <string_view>
+#include <system_error>
+
/***************************************************************************
@@ -190,86 +194,49 @@
//**************************************************************************
// pseudo-codecs returned by hunk_info
-const chd_codec_type CHD_CODEC_SELF = 1; // copy of another hunk
-const chd_codec_type CHD_CODEC_PARENT = 2; // copy of a parent's hunk
-const chd_codec_type CHD_CODEC_MINI = 3; // legacy "mini" 8-byte repeat
+constexpr chd_codec_type CHD_CODEC_SELF = 1; // copy of another hunk
+constexpr chd_codec_type CHD_CODEC_PARENT = 2; // copy of a parent's hunk
+constexpr chd_codec_type CHD_CODEC_MINI = 3; // legacy "mini" 8-byte repeat
// core types
typedef uint32_t chd_metadata_tag;
// metadata parameters
-const chd_metadata_tag CHDMETATAG_WILDCARD = 0;
-const uint32_t CHDMETAINDEX_APPEND = ~0;
+constexpr chd_metadata_tag CHDMETATAG_WILDCARD = 0;
+constexpr uint32_t CHDMETAINDEX_APPEND = ~0;
// metadata flags
-const uint8_t CHD_MDFLAGS_CHECKSUM = 0x01; // indicates data is checksummed
+constexpr uint8_t CHD_MDFLAGS_CHECKSUM = 0x01; // indicates data is checksummed
// standard hard disk metadata
-const chd_metadata_tag HARD_DISK_METADATA_TAG = CHD_MAKE_TAG('G','D','D','D');
+constexpr chd_metadata_tag HARD_DISK_METADATA_TAG = CHD_MAKE_TAG('G','D','D','D');
extern const char *HARD_DISK_METADATA_FORMAT;
// hard disk identify information
-const chd_metadata_tag HARD_DISK_IDENT_METADATA_TAG = CHD_MAKE_TAG('I','D','N','T');
+constexpr chd_metadata_tag HARD_DISK_IDENT_METADATA_TAG = CHD_MAKE_TAG('I','D','N','T');
// hard disk key information
-const chd_metadata_tag HARD_DISK_KEY_METADATA_TAG = CHD_MAKE_TAG('K','E','Y',' ');
+constexpr chd_metadata_tag HARD_DISK_KEY_METADATA_TAG = CHD_MAKE_TAG('K','E','Y',' ');
// pcmcia CIS information
-const chd_metadata_tag PCMCIA_CIS_METADATA_TAG = CHD_MAKE_TAG('C','I','S',' ');
+constexpr chd_metadata_tag PCMCIA_CIS_METADATA_TAG = CHD_MAKE_TAG('C','I','S',' ');
// standard CD-ROM metadata
-const chd_metadata_tag CDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','C','D');
-const chd_metadata_tag CDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C','H','T','R');
+constexpr chd_metadata_tag CDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','C','D');
+constexpr chd_metadata_tag CDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C','H','T','R');
extern const char *CDROM_TRACK_METADATA_FORMAT;
-const chd_metadata_tag CDROM_TRACK_METADATA2_TAG = CHD_MAKE_TAG('C','H','T','2');
+constexpr chd_metadata_tag CDROM_TRACK_METADATA2_TAG = CHD_MAKE_TAG('C','H','T','2');
extern const char *CDROM_TRACK_METADATA2_FORMAT;
-const chd_metadata_tag GDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','G','T');
-const chd_metadata_tag GDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C', 'H', 'G', 'D');
+constexpr chd_metadata_tag GDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','G','T');
+constexpr chd_metadata_tag GDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C', 'H', 'G', 'D');
extern const char *GDROM_TRACK_METADATA_FORMAT;
// standard A/V metadata
-const chd_metadata_tag AV_METADATA_TAG = CHD_MAKE_TAG('A','V','A','V');
+constexpr chd_metadata_tag AV_METADATA_TAG = CHD_MAKE_TAG('A','V','A','V');
extern const char *AV_METADATA_FORMAT;
// A/V laserdisc frame metadata
-const chd_metadata_tag AV_LD_METADATA_TAG = CHD_MAKE_TAG('A','V','L','D');
-
-// error types
-enum chd_error
-{
- CHDERR_NONE,
- CHDERR_NO_INTERFACE,
- CHDERR_OUT_OF_MEMORY,
- CHDERR_NOT_OPEN,
- CHDERR_ALREADY_OPEN,
- CHDERR_INVALID_FILE,
- CHDERR_INVALID_PARAMETER,
- CHDERR_INVALID_DATA,
- CHDERR_FILE_NOT_FOUND,
- CHDERR_REQUIRES_PARENT,
- CHDERR_FILE_NOT_WRITEABLE,
- CHDERR_READ_ERROR,
- CHDERR_WRITE_ERROR,
- CHDERR_CODEC_ERROR,
- CHDERR_INVALID_PARENT,
- CHDERR_HUNK_OUT_OF_RANGE,
- CHDERR_DECOMPRESSION_ERROR,
- CHDERR_COMPRESSION_ERROR,
- CHDERR_CANT_CREATE_FILE,
- CHDERR_CANT_VERIFY,
- CHDERR_NOT_SUPPORTED,
- CHDERR_METADATA_NOT_FOUND,
- CHDERR_INVALID_METADATA_SIZE,
- CHDERR_UNSUPPORTED_VERSION,
- CHDERR_VERIFY_INCOMPLETE,
- CHDERR_INVALID_METADATA,
- CHDERR_INVALID_STATE,
- CHDERR_OPERATION_PENDING,
- CHDERR_UNSUPPORTED_FORMAT,
- CHDERR_UNKNOWN_COMPRESSION,
- CHDERR_WALKING_PARENT,
- CHDERR_COMPRESSING
-};
+constexpr chd_metadata_tag AV_LD_METADATA_TAG = CHD_MAKE_TAG('A','V','L','D');
@@ -277,9 +244,6 @@ enum chd_error
// TYPE DEFINITIONS
//**************************************************************************
-class chd_codec;
-
-
// ======================> chd_file
// core file class
@@ -289,22 +253,49 @@ class chd_file
friend class chd_verifier;
// constants
- static const uint32_t HEADER_VERSION = 5;
- static const uint32_t V3_HEADER_SIZE = 120;
- static const uint32_t V4_HEADER_SIZE = 108;
- static const uint32_t V5_HEADER_SIZE = 124;
- static const uint32_t MAX_HEADER_SIZE = V5_HEADER_SIZE;
+ static constexpr uint32_t HEADER_VERSION = 5;
+ static constexpr uint32_t V3_HEADER_SIZE = 120;
+ static constexpr uint32_t V4_HEADER_SIZE = 108;
+ static constexpr uint32_t V5_HEADER_SIZE = 124;
+ static constexpr uint32_t MAX_HEADER_SIZE = V5_HEADER_SIZE;
public:
+ // error types
+ enum class error
+ {
+ NO_INTERFACE = 1,
+ NOT_OPEN,
+ ALREADY_OPEN,
+ INVALID_FILE,
+ INVALID_DATA,
+ REQUIRES_PARENT,
+ FILE_NOT_WRITEABLE,
+ CODEC_ERROR,
+ INVALID_PARENT,
+ HUNK_OUT_OF_RANGE,
+ DECOMPRESSION_ERROR,
+ COMPRESSION_ERROR,
+ CANT_VERIFY,
+ METADATA_NOT_FOUND,
+ INVALID_METADATA_SIZE,
+ UNSUPPORTED_VERSION,
+ VERIFY_INCOMPLETE,
+ INVALID_METADATA,
+ INVALID_STATE,
+ OPERATION_PENDING,
+ UNSUPPORTED_FORMAT,
+ UNKNOWN_COMPRESSION,
+ WALKING_PARENT,
+ COMPRESSING
+ };
+
// construction/destruction
chd_file();
virtual ~chd_file();
- // operators
- operator util::core_file &() { return *m_file; }
-
// getters
- bool opened() const { return (m_file != nullptr); }
+ util::random_read &file();
+ bool opened() const { return bool(m_file); }
uint32_t version() const { return m_version; }
uint64_t logical_bytes() const { return m_logicalbytes; }
uint32_t hunk_bytes() const { return m_hunkbytes; }
@@ -317,52 +308,49 @@ public:
util::sha1_t sha1();
util::sha1_t raw_sha1();
util::sha1_t parent_sha1();
- chd_error hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes);
+ std::error_condition hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes);
// setters
void set_raw_sha1(util::sha1_t rawdata);
void set_parent_sha1(util::sha1_t parent);
// file create
- chd_error create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]);
- chd_error create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]);
- chd_error create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent);
- chd_error create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent);
+ std::error_condition create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]);
+ std::error_condition create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]);
+ std::error_condition create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent);
+ std::error_condition create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent);
// file open
- chd_error open(const char *filename, bool writeable = false, chd_file *parent = nullptr);
- chd_error open(util::core_file &file, bool writeable = false, chd_file *parent = nullptr);
+ std::error_condition open(std::string_view filename, bool writeable = false, chd_file *parent = nullptr);
+ std::error_condition open(util::random_read_write::ptr &&file, bool writeable = false, chd_file *parent = nullptr);
// file close
void close();
// read/write
- chd_error read_hunk(uint32_t hunknum, void *buffer);
- chd_error write_hunk(uint32_t hunknum, const void *buffer);
- chd_error read_units(uint64_t unitnum, void *buffer, uint32_t count = 1);
- chd_error write_units(uint64_t unitnum, const void *buffer, uint32_t count = 1);
- chd_error read_bytes(uint64_t offset, void *buffer, uint32_t bytes);
- chd_error write_bytes(uint64_t offset, const void *buffer, uint32_t bytes);
+ std::error_condition read_hunk(uint32_t hunknum, void *buffer);
+ std::error_condition write_hunk(uint32_t hunknum, const void *buffer);
+ std::error_condition read_units(uint64_t unitnum, void *buffer, uint32_t count = 1);
+ std::error_condition write_units(uint64_t unitnum, const void *buffer, uint32_t count = 1);
+ std::error_condition read_bytes(uint64_t offset, void *buffer, uint32_t bytes);
+ std::error_condition write_bytes(uint64_t offset, const void *buffer, uint32_t bytes);
// metadata management
- chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output);
- chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output);
- chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen);
- chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output, chd_metadata_tag &resulttag, uint8_t &resultflags);
- chd_error write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags = CHD_MDFLAGS_CHECKSUM);
- chd_error write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::string &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, input.c_str(), input.length() + 1, flags); }
- chd_error write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::vector<uint8_t> &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, &input[0], input.size(), flags); }
- chd_error delete_metadata(chd_metadata_tag metatag, uint32_t metaindex);
- chd_error clone_all_metadata(chd_file &source);
+ std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output);
+ std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output);
+ std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen);
+ std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output, chd_metadata_tag &resulttag, uint8_t &resultflags);
+ std::error_condition write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags = CHD_MDFLAGS_CHECKSUM);
+ std::error_condition write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::string &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, input.c_str(), input.length() + 1, flags); }
+ std::error_condition write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::vector<uint8_t> &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, &input[0], input.size(), flags); }
+ std::error_condition delete_metadata(chd_metadata_tag metatag, uint32_t metaindex);
+ std::error_condition clone_all_metadata(chd_file &source);
// hashing helper
util::sha1_t compute_overall_sha1(util::sha1_t rawsha1);
// codec interfaces
- chd_error codec_configure(chd_codec_type codec, int param, void *config);
-
- // static helpers
- static const char *error_string(chd_error err);
+ std::error_condition codec_configure(chd_codec_type codec, int param, void *config);
private:
struct metadata_entry;
@@ -383,10 +371,10 @@ private:
void parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1);
void parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1);
void parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1);
- chd_error compress_v5_map();
+ std::error_condition compress_v5_map();
void decompress_v5_map();
- chd_error create_common();
- chd_error open_common(bool writeable);
+ std::error_condition create_common();
+ std::error_condition open_common(bool writeable);
void create_open_common();
void verify_proper_compression_append(uint32_t hunknum);
void hunk_write_compressed(uint32_t hunknum, int8_t compression, const uint8_t *compressed, uint32_t complength, util::crc16_t crc16);
@@ -398,42 +386,41 @@ private:
static int CLIB_DECL metadata_hash_compare(const void *elem1, const void *elem2);
// file characteristics
- util::core_file * m_file; // handle to the open core file
- bool m_owns_file; // flag indicating if this file should be closed on chd_close()
+ util::random_read_write::ptr m_file; // handle to the open core file
bool m_allow_reads; // permit reads from this CHD?
bool m_allow_writes; // permit writes to this CHD?
// core parameters from the header
- uint32_t m_version; // version of the header
- uint64_t m_logicalbytes; // logical size of the raw CHD data in bytes
- uint64_t m_mapoffset; // offset of map
- uint64_t m_metaoffset; // offset to first metadata bit
- uint32_t m_hunkbytes; // size of each raw hunk in bytes
- uint32_t m_hunkcount; // number of hunks represented
- uint32_t m_unitbytes; // size of each unit in bytes
- uint64_t m_unitcount; // number of units represented
+ uint32_t m_version; // version of the header
+ uint64_t m_logicalbytes; // logical size of the raw CHD data in bytes
+ uint64_t m_mapoffset; // offset of map
+ uint64_t m_metaoffset; // offset to first metadata bit
+ uint32_t m_hunkbytes; // size of each raw hunk in bytes
+ uint32_t m_hunkcount; // number of hunks represented
+ uint32_t m_unitbytes; // size of each unit in bytes
+ uint64_t m_unitcount; // number of units represented
chd_codec_type m_compression[4]; // array of compression types used
chd_file * m_parent; // pointer to parent file, or nullptr if none
bool m_parent_missing; // are we missing our parent?
// key offsets within the header
- uint64_t m_mapoffset_offset; // offset of map offset field
- uint64_t m_metaoffset_offset;// offset of metaoffset field
- uint64_t m_sha1_offset; // offset of SHA1 field
- uint64_t m_rawsha1_offset; // offset of raw SHA1 field
- uint64_t m_parentsha1_offset;// offset of paren SHA1 field
+ uint64_t m_mapoffset_offset; // offset of map offset field
+ uint64_t m_metaoffset_offset;// offset of metaoffset field
+ uint64_t m_sha1_offset; // offset of SHA1 field
+ uint64_t m_rawsha1_offset; // offset of raw SHA1 field
+ uint64_t m_parentsha1_offset;// offset of paren SHA1 field
// map information
- uint32_t m_mapentrybytes; // length of each entry in a map
- std::vector<uint8_t> m_rawmap; // raw map data
+ uint32_t m_mapentrybytes; // length of each entry in a map
+ std::vector<uint8_t> m_rawmap; // raw map data
// compression management
- chd_decompressor * m_decompressor[4]; // array of decompression codecs
- std::vector<uint8_t> m_compressed; // temporary buffer for compressed data
+ chd_decompressor::ptr m_decompressor[4]; // array of decompression codecs
+ std::vector<uint8_t> m_compressed; // temporary buffer for compressed data
// caching
- std::vector<uint8_t> m_cache; // single-hunk cache for partial reads/writes
- uint32_t m_cachehunk; // which hunk is in the cache?
+ std::vector<uint8_t> m_cache; // single-hunk cache for partial reads/writes
+ uint32_t m_cachehunk; // which hunk is in the cache?
};
@@ -449,7 +436,7 @@ public:
// compression management
void compress_begin();
- chd_error compress_continue(double &progress, double &ratio);
+ std::error_condition compress_continue(double &progress, double &ratio);
protected:
// required override: read more data
@@ -470,24 +457,24 @@ private:
void add(uint64_t itemnum, util::crc16_t crc16, util::sha1_t sha1);
// constants
- static const uint64_t NOT_FOUND = ~uint64_t(0);
+ static constexpr uint64_t NOT_FOUND = ~uint64_t(0);
+
private:
// internal entry
struct entry_t
{
entry_t * m_next; // next entry in list
- uint64_t m_itemnum; // item number
+ uint64_t m_itemnum; // item number
util::sha1_t m_sha1; // SHA-1 of the block
};
// block of entries
struct entry_block
{
- entry_block(entry_block *prev)
- : m_next(prev), m_nextalloc(0) { }
+ entry_block(entry_block *prev) : m_next(prev), m_nextalloc(0) { }
entry_block * m_next; // next block in list
- uint32_t m_nextalloc; // next to be allocated
+ uint32_t m_nextalloc; // next to be allocated
entry_t m_array[16384]; // array of entries
};
@@ -551,8 +538,8 @@ private:
// current compression status
bool m_walking_parent; // are we building the parent map?
- uint64_t m_total_in; // total bytes in
- uint64_t m_total_out; // total bytes out
+ uint64_t m_total_in; // total bytes in
+ uint64_t m_total_out; // total bytes out
util::sha1_creator m_compsha1; // running SHA-1 on raw data
// hash lookup maps
@@ -561,20 +548,31 @@ private:
// read I/O thread
osd_work_queue * m_read_queue; // work queue for reading
- uint64_t m_read_queue_offset;// next offset to enqueue
- uint64_t m_read_done_offset; // next offset that will complete
+ uint64_t m_read_queue_offset;// next offset to enqueue
+ uint64_t m_read_done_offset; // next offset that will complete
bool m_read_error; // error during reading?
// work item thread
- static const int WORK_BUFFER_HUNKS = 256;
+ static constexpr int WORK_BUFFER_HUNKS = 256;
osd_work_queue * m_work_queue; // queue for doing work on other threads
- std::vector<uint8_t> m_work_buffer; // buffer containing hunk data to work on
- std::vector<uint8_t> m_compressed_buffer;// buffer containing compressed data
+ std::vector<uint8_t> m_work_buffer; // buffer containing hunk data to work on
+ std::vector<uint8_t> m_compressed_buffer;// buffer containing compressed data
work_item m_work_item[WORK_BUFFER_HUNKS]; // status of each hunk
chd_compressor_group * m_codecs[WORK_MAX_THREADS]; // codecs to use
// output state
- uint32_t m_write_hunk; // next hunk to write
+ uint32_t m_write_hunk; // next hunk to write
};
-#endif // MAME_UTIL_CHD_H
+
+// error category for CHD errors
+std::error_category const &chd_category() noexcept;
+inline std::error_condition make_error_condition(chd_file::error err) noexcept { return std::error_condition(int(err), chd_category()); }
+
+namespace std {
+
+template <> struct is_error_condition_enum<chd_file::error> : public std::true_type { };
+
+} // namespace std
+
+#endif // MAME_LIB_UTIL_CHD_H