summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/imagedev/harddriv.cpp56
-rw-r--r--src/devices/imagedev/harddriv.h2
-rw-r--r--src/devices/machine/idehd.cpp2
-rw-r--r--src/lib/util/harddisk.cpp77
-rw-r--r--src/lib/util/harddisk.h3
5 files changed, 118 insertions, 22 deletions
diff --git a/src/devices/imagedev/harddriv.cpp b/src/devices/imagedev/harddriv.cpp
index 145ce0ebdbb..b4e93fcd200 100644
--- a/src/devices/imagedev/harddriv.cpp
+++ b/src/devices/imagedev/harddriv.cpp
@@ -75,7 +75,7 @@ harddisk_image_device::~harddisk_image_device()
void harddisk_image_device::device_config_complete()
{
- add_format("chd", "CHD Hard drive", "chd,hd", hd_option_spec);
+ add_format("chd", "CHD Hard drive", "chd,hd,hdv,2mg", hd_option_spec);
}
const util::option_guide &harddisk_image_device::create_option_guide() const
@@ -176,8 +176,11 @@ void harddisk_image_device::call_unload()
m_hard_disk_handle = nullptr;
}
- m_origchd.close();
- m_diffchd.close();
+ if (m_chd)
+ {
+ m_origchd.close();
+ m_diffchd.close();
+ }
m_chd = nullptr;
}
@@ -227,7 +230,6 @@ static chd_error open_disk_diff(emu_options &options, const char *name, chd_file
image_init_result harddisk_image_device::internal_load_hd()
{
chd_error err = CHDERR_NONE;
-
m_chd = nullptr;
if (m_hard_disk_handle != nullptr)
@@ -243,20 +245,24 @@ image_init_result harddisk_image_device::internal_load_hd()
}
else
{
- err = m_origchd.open(image_core_file(), true);
- if (err == CHDERR_NONE)
+ if (is_filetype("chd"))
{
- m_chd = &m_origchd;
- }
- else if (err == CHDERR_FILE_NOT_WRITEABLE)
- {
- err = m_origchd.open(image_core_file(), false);
+ err = m_origchd.open(image_core_file(), true);
+
if (err == CHDERR_NONE)
{
- err = open_disk_diff(device().machine().options(), basename_noext(), m_origchd, m_diffchd);
+ m_chd = &m_origchd;
+ }
+ else if (err == CHDERR_FILE_NOT_WRITEABLE)
+ {
+ err = m_origchd.open(image_core_file(), false);
if (err == CHDERR_NONE)
{
- m_chd = &m_diffchd;
+ err = open_disk_diff(device().machine().options(), basename_noext(), m_origchd, m_diffchd);
+ if (err == CHDERR_NONE)
+ {
+ m_chd = &m_diffchd;
+ }
}
}
}
@@ -269,6 +275,30 @@ image_init_result harddisk_image_device::internal_load_hd()
if (m_hard_disk_handle != nullptr)
return image_init_result::PASS;
}
+ else
+ {
+ if (is_open())
+ {
+ uint32_t skip = 0;
+ char header[64];
+
+ fseek(0, SEEK_SET);
+ fread(header, 64);
+
+ // check for 2MG format
+ if (!memcmp(header, "2IMG", 4))
+ {
+ skip = header[0x18] | (header[0x19] << 8) | (header[0x1a] << 16) | (header[0x1b] << 24);
+ osd_printf_verbose("harddriv: found 2MG, creator is %c%c%c%c, data at %08x\n", header[4], header[5], header[6], header[7], skip);
+ }
+
+ m_hard_disk_handle = hard_disk_open(image_core_file(), skip);
+ if (m_hard_disk_handle != nullptr)
+ return image_init_result::PASS;
+ }
+
+ return image_init_result::FAIL;
+ }
/* if we had an error, close out the CHD */
m_origchd.close();
diff --git a/src/devices/imagedev/harddriv.h b/src/devices/imagedev/harddriv.h
index 425b75d6eed..ab077ef8d38 100644
--- a/src/devices/imagedev/harddriv.h
+++ b/src/devices/imagedev/harddriv.h
@@ -51,7 +51,7 @@ public:
virtual bool must_be_loaded() const override { return 0; }
virtual bool is_reset_on_load() const override { return 0; }
virtual const char *image_interface() const override { return m_interface; }
- virtual const char *file_extensions() const override { return "chd,hd"; }
+ virtual const char *file_extensions() const override { return "chd,hd,hdv,2mg"; }
virtual const util::option_guide &create_option_guide() const override;
// specific implementation
diff --git a/src/devices/machine/idehd.cpp b/src/devices/machine/idehd.cpp
index e0ce5098e9a..e442e4475f6 100644
--- a/src/devices/machine/idehd.cpp
+++ b/src/devices/machine/idehd.cpp
@@ -838,7 +838,7 @@ void ide_hdd_device::device_reset()
// build the features page
uint32_t metalength;
- if (m_handle->read_metadata (HARD_DISK_IDENT_METADATA_TAG, 0, &m_buffer[0], 512, metalength) == CHDERR_NONE)
+ if (m_handle && m_handle->read_metadata (HARD_DISK_IDENT_METADATA_TAG, 0, &m_buffer[0], 512, metalength) == CHDERR_NONE)
{
for( int w = 0; w < 256; w++ )
{
diff --git a/src/lib/util/harddisk.cpp b/src/lib/util/harddisk.cpp
index 31c6a36ed28..5db97e3417b 100644
--- a/src/lib/util/harddisk.cpp
+++ b/src/lib/util/harddisk.cpp
@@ -9,12 +9,10 @@
***************************************************************************/
#include <assert.h>
-
#include "harddisk.h"
-
+#include "osdcore.h"
#include <stdlib.h>
-
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
@@ -22,6 +20,7 @@
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 */
};
@@ -63,10 +62,49 @@ hard_disk_file *hard_disk_open(chd_file *chd)
/* 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;
+}
+
+hard_disk_file *hard_disk_open(util::core_file &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;
+
+ // 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 cursectors = 63; cursectors > 1; cursectors--)
+ if (totalsectors % cursectors == 0)
+ {
+ uint32_t totalheads = totalsectors / cursectors;
+ 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;
+ }
+ }
+
return file;
}
@@ -77,6 +115,11 @@ hard_disk_file *hard_disk_open(chd_file *chd)
void hard_disk_close(hard_disk_file *file)
{
+ if (file->fhandle)
+ {
+ file->fhandle->flush();
+ }
+
free(file);
}
@@ -132,8 +175,18 @@ hard_disk_info *hard_disk_get_info(hard_disk_file *file)
uint32_t hard_disk_read(hard_disk_file *file, uint32_t lbasector, void *buffer)
{
- chd_error err = file->chd->read_units(lbasector, buffer);
- return (err == CHDERR_NONE);
+ if (file->chd)
+ {
+ chd_error err = file->chd->read_units(lbasector, buffer);
+ return (err == CHDERR_NONE);
+ }
+ 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);
+ }
}
@@ -156,6 +209,16 @@ uint32_t hard_disk_read(hard_disk_file *file, uint32_t lbasector, void *buffer)
uint32_t hard_disk_write(hard_disk_file *file, uint32_t lbasector, const void *buffer)
{
- chd_error err = file->chd->write_units(lbasector, buffer);
- return (err == CHDERR_NONE);
+ if (file->chd)
+ {
+ chd_error err = file->chd->write_units(lbasector, buffer);
+ return (err == CHDERR_NONE);
+ }
+ 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);
+ }
}
diff --git a/src/lib/util/harddisk.h b/src/lib/util/harddisk.h
index c0551703ca7..2a4b727e7e7 100644
--- a/src/lib/util/harddisk.h
+++ b/src/lib/util/harddisk.h
@@ -29,6 +29,7 @@ struct hard_disk_info
uint32_t heads;
uint32_t sectors;
uint32_t sectorbytes;
+ uint32_t fileoffset; // offset in the file where the HDD image starts. not valid for CHDs.
};
@@ -38,6 +39,8 @@ struct hard_disk_info
***************************************************************************/
hard_disk_file *hard_disk_open(chd_file *chd);
+hard_disk_file *hard_disk_open(util::core_file &corefile, uint32_t skipoffs);
+
void hard_disk_close(hard_disk_file *file);
chd_file *hard_disk_get_chd(hard_disk_file *file);