diff options
Diffstat (limited to 'src/lib/util/harddisk.cpp')
-rw-r--r-- | src/lib/util/harddisk.cpp | 245 |
1 files changed, 121 insertions, 124 deletions
diff --git a/src/lib/util/harddisk.cpp b/src/lib/util/harddisk.cpp index 5db97e3417b..266e5d25a2b 100644 --- a/src/lib/util/harddisk.cpp +++ b/src/lib/util/harddisk.cpp @@ -8,88 +8,62 @@ ***************************************************************************/ -#include <assert.h> #include "harddisk.h" -#include "osdcore.h" -#include <stdlib.h> -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ +#include "chd.h" +#include "ioprocs.h" -struct hard_disk_file -{ - chd_file * chd; /* CHD file */ - util::core_file *fhandle; /* core_file if not a CHD */ - hard_disk_info info; /* hard disk info */ -}; +#include "osdcore.h" +#include <cstdlib> +#include <tuple> -/*************************************************************************** - CORE IMPLEMENTATION -***************************************************************************/ - /*------------------------------------------------- - hard_disk_open - open a hard disk handle, + constructor - open a hard disk handle, given a chd_file -------------------------------------------------*/ -hard_disk_file *hard_disk_open(chd_file *chd) +hard_disk_file::hard_disk_file(chd_file *_chd) { - int cylinders, heads, sectors, sectorbytes; - hard_disk_file *file; + chd = _chd; + fhandle = nullptr; + fileoffset = 0; + std::string metadata; - chd_error err; + std::error_condition err; /* punt if no CHD */ if (chd == nullptr) - return nullptr; + throw nullptr; /* read the hard disk metadata */ - err = chd->read_metadata(HARD_DISK_METADATA_TAG, 0, metadata); - if (err != CHDERR_NONE) - return nullptr; + err = _chd->read_metadata(HARD_DISK_METADATA_TAG, 0, metadata); + if (err) + throw nullptr; /* parse the metadata */ - if (sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &cylinders, &heads, §ors, §orbytes) != 4) - return nullptr; - - /* allocate memory for the hard disk file */ - file = (hard_disk_file *)malloc(sizeof(hard_disk_file)); - if (file == nullptr) - return nullptr; - - /* fill in the data */ - file->chd = chd; - file->fhandle = nullptr; - file->info.cylinders = cylinders; - file->info.heads = heads; - file->info.sectors = sectors; - file->info.sectorbytes = sectorbytes; - file->info.fileoffset = 0; - return file; + if (sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &hdinfo.cylinders, &hdinfo.heads, &hdinfo.sectors, &hdinfo.sectorbytes) != 4) + throw nullptr; } -hard_disk_file *hard_disk_open(util::core_file &corefile, uint32_t skipoffs) +hard_disk_file::hard_disk_file(util::random_read_write &corefile, uint32_t skipoffs) { - hard_disk_file *file; - - /* allocate memory for the hard disk file */ - file = (hard_disk_file *)malloc(sizeof(hard_disk_file)); - if (file == nullptr) - return nullptr; - - file->chd = nullptr; - file->fhandle = &corefile; - file->info.sectorbytes = 512; - file->info.cylinders = 0; - file->info.heads = 0; - file->info.sectors = 0; - file->info.fileoffset = skipoffs; + // bail if getting the file length fails + std::uint64_t length; + if (corefile.length(length)) + throw nullptr; + + chd = nullptr; + fhandle = &corefile; + hdinfo.sectorbytes = 512; + hdinfo.cylinders = 0; + hdinfo.heads = 0; + hdinfo.sectors = 0; + fileoffset = skipoffs; // attempt to guess geometry in case this is an ATA situation - for (uint32_t totalsectors = (corefile.size() - skipoffs) / file->info.sectorbytes; ; totalsectors++) + for (uint32_t totalsectors = (length - skipoffs) / hdinfo.sectorbytes; ; totalsectors++) for (uint32_t cursectors = 63; cursectors > 1; cursectors--) if (totalsectors % cursectors == 0) { @@ -97,128 +71,151 @@ hard_disk_file *hard_disk_open(util::core_file &corefile, uint32_t skipoffs) for (uint32_t curheads = 16; curheads > 1; curheads--) if (totalheads % curheads == 0) { - file->info.cylinders = totalheads / curheads; - file->info.heads = curheads; - file->info.sectors = cursectors; - osd_printf_verbose("Guessed CHS of %d/%d/%d\n", file->info.cylinders, file->info.heads, file->info.sectors); - return file; + hdinfo.cylinders = totalheads / curheads; + hdinfo.heads = curheads; + hdinfo.sectors = cursectors; + osd_printf_verbose("Guessed CHS of %d/%d/%d\n", hdinfo.cylinders, hdinfo.heads, hdinfo.sectors); + return; } } - - return file; -} - - -/*------------------------------------------------- - hard_disk_close - close a hard disk handle --------------------------------------------------*/ - -void hard_disk_close(hard_disk_file *file) -{ - if (file->fhandle) - { - file->fhandle->flush(); - } - - free(file); } /*------------------------------------------------- - hard_disk_get_chd - get a handle to a CHD - from a hard disk + destructor - close a hard disk handle -------------------------------------------------*/ -chd_file *hard_disk_get_chd(hard_disk_file *file) +hard_disk_file::~hard_disk_file() { - return file->chd; + if (fhandle) + fhandle->flush(); } /*------------------------------------------------- - hard_disk_get_info - return information about - a hard disk + read - read sectors from a hard disk -------------------------------------------------*/ /** - * @fn hard_disk_info *hard_disk_get_info(hard_disk_file *file) + * @fn bool read(uint32_t lbasector, void *buffer) * - * @brief Hard disk get information. + * @brief Hard disk read. * - * @param [in,out] file If non-null, the file. + * @param lbasector The sector number (Linear Block Address) to read. + * @param buffer The buffer where the hard disk data will be placed. * - * @return null if it fails, else a hard_disk_info*. + * @return True if the operation succeeded */ -hard_disk_info *hard_disk_get_info(hard_disk_file *file) +bool hard_disk_file::read(uint32_t lbasector, void *buffer) { - return &file->info; + if (chd) + { + std::error_condition err = chd->read_units(lbasector, buffer); + return !err; + } + else + { + size_t actual = 0; + std::error_condition err = fhandle->seek(fileoffset + (lbasector * hdinfo.sectorbytes), SEEK_SET); + if (!err) + std::tie(err, actual) = util::read(*fhandle, buffer, hdinfo.sectorbytes); + return !err && (actual == hdinfo.sectorbytes); + } } /*------------------------------------------------- - hard_disk_read - read sectors from a hard - disk + write - write sectors to a hard disk -------------------------------------------------*/ /** - * @fn uint32_t hard_disk_read(hard_disk_file *file, uint32_t lbasector, void *buffer) + * @fn bool write(uint32_t lbasector, const void *buffer) * - * @brief Hard disk read. + * @brief Hard disk write. * - * @param [in,out] file If non-null, the file. - * @param lbasector The lbasector. - * @param [in,out] buffer If non-null, the buffer. + * @param lbasector The sector number (Linear Block Address) to write. + * @param buffer The buffer containing the data to write. * - * @return An uint32_t. + * @return True if the operation succeeded */ -uint32_t hard_disk_read(hard_disk_file *file, uint32_t lbasector, void *buffer) +bool hard_disk_file::write(uint32_t lbasector, const void *buffer) { - if (file->chd) + if (chd) { - chd_error err = file->chd->read_units(lbasector, buffer); - return (err == CHDERR_NONE); + std::error_condition err = chd->write_units(lbasector, buffer); + return !err; } else { - uint32_t actual = 0; - file->fhandle->seek(file->info.fileoffset + (lbasector * file->info.sectorbytes), SEEK_SET); - actual = file->fhandle->read(buffer, file->info.sectorbytes); - return (actual == file->info.sectorbytes); + size_t actual = 0; + std::error_condition err = fhandle->seek(fileoffset + (lbasector * hdinfo.sectorbytes), SEEK_SET); + if (!err) + std::tie(err, actual) = util::write(*fhandle, buffer, hdinfo.sectorbytes); + return !err; } } /*------------------------------------------------- - hard_disk_write - write sectors to a hard - disk + set_block_size - sets the block size + for a non-CHD-backed hard disk (a bare file). -------------------------------------------------*/ /** - * @fn uint32_t hard_disk_write(hard_disk_file *file, uint32_t lbasector, const void *buffer) + * @fn bool set_block_size(uint32_t blocksize) * - * @brief Hard disk write. + * @brief Hard disk set block size (works only for non-CHD-files) * - * @param [in,out] file If non-null, the file. - * @param lbasector The lbasector. - * @param buffer The buffer. + * @param blocksize The block size of this hard disk, in bytes. * - * @return An uint32_t. + * @return true on success, false on failure. Failure means a CHD is in use and the CHD + * block size does not match the passed in size. If a CHD is in use and the block + * sizes match, success is returned). */ -uint32_t hard_disk_write(hard_disk_file *file, uint32_t lbasector, const void *buffer) +bool hard_disk_file::set_block_size(uint32_t blocksize) { - if (file->chd) + if (chd) { - chd_error err = file->chd->write_units(lbasector, buffer); - return (err == CHDERR_NONE); + // if the CHD block size matches our block size, we're OK. + if (chd->unit_bytes() == blocksize) + { + return true; + } + + // indicate failure, since we can't change the block size of a CHD. + return false; } else { - uint32_t actual = 0; - file->fhandle->seek(file->info.fileoffset + (lbasector * file->info.sectorbytes), SEEK_SET); - actual = file->fhandle->write(buffer, file->info.sectorbytes); - return (actual == file->info.sectorbytes); + hdinfo.sectorbytes = blocksize; + return true; } } + + +std::error_condition hard_disk_file::get_inquiry_data(std::vector<uint8_t> &data) const +{ + if(chd) + return chd->read_metadata(HARD_DISK_IDENT_METADATA_TAG, 0, data); + else + return std::error_condition(chd_file::error::METADATA_NOT_FOUND); +} + +std::error_condition hard_disk_file::get_cis_data(std::vector<uint8_t> &data) const +{ + if(chd) + return chd->read_metadata(PCMCIA_CIS_METADATA_TAG, 0, data); + else + return std::error_condition(chd_file::error::METADATA_NOT_FOUND); +} + +std::error_condition hard_disk_file::get_disk_key_data(std::vector<uint8_t> &data) const +{ + if(chd) + return chd->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, data); + else + return std::error_condition(chd_file::error::METADATA_NOT_FOUND); +} |