summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/harddisk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/harddisk.cpp')
-rw-r--r--src/lib/util/harddisk.cpp245
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, &sectors, &sectorbytes) != 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);
+}