summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/tools/imgtool/imghd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/tools/imgtool/imghd.c')
-rw-r--r--src/mame/tools/imgtool/imghd.c273
1 files changed, 273 insertions, 0 deletions
diff --git a/src/mame/tools/imgtool/imghd.c b/src/mame/tools/imgtool/imghd.c
new file mode 100644
index 00000000000..8ac129751f9
--- /dev/null
+++ b/src/mame/tools/imgtool/imghd.c
@@ -0,0 +1,273 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods, Raphael Nabet
+/*
+ Code to interface the MESS image code with MAME's harddisk core.
+
+ We do not support diff files as it will involve some changes in the MESS
+ image code.
+
+ Raphael Nabet 2003
+*/
+
+#include "imgtool.h"
+#include "harddisk.h"
+#include "imghd.h"
+
+
+static imgtoolerr_t map_chd_error(chd_error chderr)
+{
+ imgtoolerr_t err;
+
+ switch(chderr)
+ {
+ case CHDERR_NONE:
+ err = IMGTOOLERR_SUCCESS;
+ break;
+ case CHDERR_OUT_OF_MEMORY:
+ err = IMGTOOLERR_OUTOFMEMORY;
+ break;
+ case CHDERR_FILE_NOT_WRITEABLE:
+ err = IMGTOOLERR_READONLY;
+ break;
+ case CHDERR_NOT_SUPPORTED:
+ err = IMGTOOLERR_UNIMPLEMENTED;
+ break;
+ default:
+ err = IMGTOOLERR_UNEXPECTED;
+ break;
+ }
+ return err;
+}
+
+
+
+/*
+ imghd_create()
+
+ Create a MAME HD image
+*/
+imgtoolerr_t imghd_create(imgtool_stream *stream, UINT32 hunksize, UINT32 cylinders, UINT32 heads, UINT32 sectors, UINT32 seclen)
+{
+ imgtoolerr_t err = IMGTOOLERR_SUCCESS;
+ dynamic_buffer cache;
+ chd_file chd;
+ chd_error rc;
+ UINT64 logicalbytes;
+ int hunknum, totalhunks;
+ std::string metadata;
+ chd_codec_type compression[4] = { CHD_CODEC_NONE };
+
+ /* sanity check args */
+ if (hunksize >= 2048)
+ {
+ err = IMGTOOLERR_PARAMCORRUPT;
+ goto done;
+ }
+ if (hunksize <= 0)
+ hunksize = 1024; /* default value */
+
+ /* bail if we are read only */
+ if (stream_isreadonly(stream))
+ {
+ err = IMGTOOLERR_READONLY;
+ goto done;
+ }
+
+ /* calculations */
+ logicalbytes = (UINT64)cylinders * heads * sectors * seclen;
+
+ /* create the new hard drive */
+ rc = chd.create(*stream_core_file(stream), logicalbytes, hunksize, seclen, compression);
+ if (rc != CHDERR_NONE)
+ {
+ err = map_chd_error(rc);
+ goto done;
+ }
+
+ /* open the new hard drive */
+ rc = chd.open(*stream_core_file(stream));
+
+ if (rc != CHDERR_NONE)
+ {
+ err = map_chd_error(rc);
+ goto done;
+ }
+
+ /* write the metadata */
+ strprintf(metadata,HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, seclen);
+ err = (imgtoolerr_t)chd.write_metadata(HARD_DISK_METADATA_TAG, 0, metadata);
+ if (rc != CHDERR_NONE)
+ {
+ err = map_chd_error(rc);
+ goto done;
+ }
+
+ /* alloc and zero buffer */
+ cache.resize(hunksize);
+ memset(&cache[0], 0, hunksize);
+
+ /* zero out every hunk */
+ totalhunks = (logicalbytes + hunksize - 1) / hunksize;
+ for (hunknum = 0; hunknum < totalhunks; hunknum++)
+ {
+ rc = chd.write_units(hunknum, &cache[0]);
+ if (rc)
+ {
+ err = IMGTOOLERR_WRITEERROR;
+ goto done;
+ }
+ }
+
+done:
+ return err;
+}
+
+
+
+/*
+ imghd_open()
+
+ Open stream as a MAME HD image
+*/
+imgtoolerr_t imghd_open(imgtool_stream *stream, struct mess_hard_disk_file *hard_disk)
+{
+ chd_error chderr;
+ imgtoolerr_t err = IMGTOOLERR_SUCCESS;
+
+ hard_disk->hard_disk = NULL;
+ hard_disk->chd = NULL;
+
+ chderr = hard_disk->chd->open(*stream_core_file(stream), stream_isreadonly(stream));
+ if (chderr)
+ {
+ err = map_chd_error(chderr);
+ goto done;
+ }
+
+ hard_disk->hard_disk = hard_disk_open(hard_disk->chd);
+ if (!hard_disk->hard_disk)
+ {
+ err = IMGTOOLERR_UNEXPECTED;
+ goto done;
+ }
+ hard_disk->stream = stream;
+
+done:
+ if (err)
+ imghd_close(hard_disk);
+ return err;
+}
+
+
+
+/*
+ imghd_close()
+
+ Close MAME HD image
+*/
+void imghd_close(struct mess_hard_disk_file *disk)
+{
+ if (disk->hard_disk)
+ {
+ hard_disk_close(disk->hard_disk);
+ disk->hard_disk = NULL;
+ }
+ if (disk->stream)
+ stream_close(disk->stream);
+}
+
+
+
+/*
+ imghd_read()
+
+ Read sector(s) from MAME HD image
+*/
+imgtoolerr_t imghd_read(struct mess_hard_disk_file *disk, UINT32 lbasector, void *buffer)
+{
+ UINT32 reply;
+ reply = hard_disk_read(disk->hard_disk, lbasector, buffer);
+ return (imgtoolerr_t)(reply ? IMGTOOLERR_SUCCESS : map_chd_error((chd_error)reply));
+}
+
+
+
+/*
+ imghd_write()
+
+ Write sector(s) from MAME HD image
+*/
+imgtoolerr_t imghd_write(struct mess_hard_disk_file *disk, UINT32 lbasector, const void *buffer)
+{
+ UINT32 reply;
+ reply = hard_disk_write(disk->hard_disk, lbasector, buffer);
+ return (imgtoolerr_t)(reply ? IMGTOOLERR_SUCCESS : map_chd_error((chd_error)reply));
+}
+
+
+
+/*
+ imghd_get_header()
+
+ Return pointer to the header of MAME HD image
+*/
+const hard_disk_info *imghd_get_header(struct mess_hard_disk_file *disk)
+{
+ const hard_disk_info *reply;
+ reply = hard_disk_get_info(disk->hard_disk);
+ return reply;
+}
+
+
+static imgtoolerr_t mess_hd_image_create(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions);
+
+enum
+{
+ mess_hd_createopts_blocksize = 'B',
+ mess_hd_createopts_cylinders = 'C',
+ mess_hd_createopts_heads = 'D',
+ mess_hd_createopts_sectors = 'E',
+ mess_hd_createopts_seclen = 'F'
+};
+
+static OPTION_GUIDE_START( mess_hd_create_optionguide )
+ OPTION_INT(mess_hd_createopts_blocksize, "blocksize", "Sectors Per Block" )
+ OPTION_INT(mess_hd_createopts_cylinders, "cylinders", "Cylinders" )
+ OPTION_INT(mess_hd_createopts_heads, "heads", "Heads" )
+ OPTION_INT(mess_hd_createopts_sectors, "sectors", "Total Sectors" )
+ OPTION_INT(mess_hd_createopts_seclen, "seclen", "Sector Bytes" )
+OPTION_GUIDE_END
+
+#define mess_hd_create_optionspecs "B[1]-2048;C1-[32]-65536;D1-[8]-64;E1-[128]-4096;F128/256/[512]/1024/2048/4096/8192/16384/32768/65536"
+
+
+void hd_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
+{
+ switch(state)
+ {
+ case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "mess_hd"); break;
+ case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "MESS hard disk image"); break;
+ case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "hd"); break;
+
+ case IMGTOOLINFO_PTR_CREATE: info->create = mess_hd_image_create; break;
+
+ case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = mess_hd_create_optionguide; break;
+ case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), mess_hd_create_optionspecs); break;
+ }
+}
+
+
+
+static imgtoolerr_t mess_hd_image_create(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions)
+{
+ UINT32 blocksize, cylinders, heads, sectors, seclen;
+
+ /* read options */
+ blocksize = option_resolution_lookup_int(createoptions, mess_hd_createopts_blocksize);
+ cylinders = option_resolution_lookup_int(createoptions, mess_hd_createopts_cylinders);
+ heads = option_resolution_lookup_int(createoptions, mess_hd_createopts_heads);
+ sectors = option_resolution_lookup_int(createoptions, mess_hd_createopts_sectors);
+ seclen = option_resolution_lookup_int(createoptions, mess_hd_createopts_seclen);
+
+ return imghd_create(f, blocksize, cylinders, heads, sectors, seclen);
+}