From 8709e06b673765ef76594de2878a4c48aa011b42 Mon Sep 17 00:00:00 2001 From: Olivier Galibert Date: Wed, 28 Apr 2021 16:17:41 +0200 Subject: [PATCH] floppy: start block-devicing fielsystem support --- scripts/src/formats.lua | 14 ++ src/devices/bus/oricext/jasmin.cpp | 6 +- src/devices/imagedev/floppy.cpp | 19 +- src/devices/imagedev/floppy.h | 17 +- src/frontend/mame/ui/floppycntrl.cpp | 4 +- src/lib/formats/all.cpp | 8 + src/lib/formats/flopimg.cpp | 3 + src/lib/formats/fs_oric_jasmin.cpp | 113 ++++++++++ src/lib/formats/fs_oric_jasmin.h | 35 +++ src/lib/formats/fs_prodos.cpp | 91 +++++--- src/lib/formats/fs_prodos.h | 18 +- src/lib/formats/fs_unformatted.cpp | 54 +++-- src/lib/formats/fs_unformatted.h | 17 +- src/lib/formats/fsblk_vec.cpp | 39 ++++ src/lib/formats/fsblk_vec.h | 33 +++ src/lib/formats/fsmgr.cpp | 136 +++++++++--- src/lib/formats/fsmgr.h | 318 +++++++++++++++++++++++++-- src/lib/formats/oric_dsk.cpp | 98 ++++++++- src/lib/formats/oric_dsk.h | 19 +- src/tools/floptool.cpp | 51 +++-- 20 files changed, 950 insertions(+), 143 deletions(-) create mode 100644 src/lib/formats/fs_oric_jasmin.cpp create mode 100644 src/lib/formats/fs_oric_jasmin.h create mode 100644 src/lib/formats/fsblk_vec.cpp create mode 100644 src/lib/formats/fsblk_vec.h diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua index 52af636f2ef..2e54bfaa999 100644 --- a/scripts/src/formats.lua +++ b/scripts/src/formats.lua @@ -72,6 +72,8 @@ project "formats" MAME_DIR .. "src/lib/formats/fsmgr.h", MAME_DIR .. "src/lib/formats/fsmgr.cpp", + MAME_DIR .. "src/lib/formats/fsblk_vec.h", + MAME_DIR .. "src/lib/formats/fsblk_vec.cpp", MAME_DIR .. "src/lib/formats/fs_unformatted.h", MAME_DIR .. "src/lib/formats/fs_unformatted.cpp", } @@ -2069,4 +2071,16 @@ if opt_tool(FORMATS, "FS_PRODOS") then } end +-------------------------------------------------- +-- +--@src/lib/formats/fs_oric_jasmin.h,FORMATS["FS_ORIC_JASMIN"] = true +-------------------------------------------------- + +if opt_tool(FORMATS, "FS_ORIC_JASMIN") then + files { + MAME_DIR.. "src/lib/formats/fs_oric_jasmin.cpp", + MAME_DIR.. "src/lib/formats/fs_oric_jasmin.h", + } +end + end diff --git a/src/devices/bus/oricext/jasmin.cpp b/src/devices/bus/oricext/jasmin.cpp index dabae07c7c9..a7188667b09 100644 --- a/src/devices/bus/oricext/jasmin.cpp +++ b/src/devices/bus/oricext/jasmin.cpp @@ -3,6 +3,7 @@ #include "emu.h" #include "jasmin.h" #include "formats/oric_dsk.h" +#include "formats/fs_oric_jasmin.h" DEFINE_DEVICE_TYPE(ORIC_JASMIN, oric_jasmin_device, "oric_jasmin", "Jasmin floppy drive interface") @@ -15,6 +16,9 @@ void oric_jasmin_device::floppy_formats(format_registration &fr) { fr.add_mfm_containers(); fr.add(FLOPPY_ORIC_DSK_FORMAT); + fr.add(FLOPPY_ORIC_JASMIN_FORMAT); + + fr.add(FS_ORIC_JASMIN); } static void jasmin_floppies(device_slot_interface &device) @@ -24,7 +28,7 @@ static void jasmin_floppies(device_slot_interface &device) INPUT_PORTS_START( jasmin ) PORT_START("JASMIN") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Boot") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CHANGED_MEMBER(DEVICE_SELF, oric_jasmin_device, boot_pressed, 0) + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Boot") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CHANGED_MEMBER(DEVICE_SELF, oric_jasmin_device, boot_pressed, 0) INPUT_PORTS_END void oric_jasmin_device::map(address_map &map) diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp index b01a7943935..2decede8498 100644 --- a/src/devices/imagedev/floppy.cpp +++ b/src/devices/imagedev/floppy.cpp @@ -21,6 +21,7 @@ #include "formats/pc_dsk.h" #include "formats/fs_unformatted.h" +#include "formats/fsblk_vec.h" #include "speaker.h" #include "formats/imageutl.h" @@ -308,14 +309,17 @@ void floppy_image_device::setup_led_cb(led_cb cb) cur_led_cb = cb; } -void floppy_image_device::fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) +void floppy_image_device::fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) { - m_fid->m_fs.emplace_back(fs_info(manager, type, image_size, name, key, description)); + if(manager->can_format()) + m_fid->m_create_fs.emplace_back(fs_info(manager, type, image_size, name, description)); + if(manager->can_read()) + m_fid->m_io_fs.emplace_back(fs_info(manager, type, image_size, name, description)); } -void floppy_image_device::fs_enum::add_raw(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) +void floppy_image_device::fs_enum::add_raw(const char *name, u32 key, const char *description) { - m_fid->m_fs.emplace_back(fs_info(manager, name, key, description)); + m_fid->m_create_fs.emplace_back(fs_info(name, key, description)); } void floppy_image_device::register_formats() @@ -718,14 +722,17 @@ void floppy_image_device::init_fs(const fs_info *fs) if (fs->m_type) { std::vector img(fs->m_image_size); - fs->m_manager->floppy_instantiate(fs->m_key, img); + fsblk_vec_t blockdev(img); + auto cfs = fs->m_manager->mount(blockdev); + cfs->format(); + auto iog = ram_open(img); auto source_format = fs->m_type(); source_format->load(iog, floppy_image::FF_UNKNOWN, variants, image.get()); delete source_format; delete iog; } else - fs->m_manager->floppy_instantiate_raw(fs->m_key, image.get()); + fs_unformatted::format(fs->m_key, image.get()); } /* write protect, active high diff --git a/src/devices/imagedev/floppy.h b/src/devices/imagedev/floppy.h index f847e525a05..0747e1bef3a 100644 --- a/src/devices/imagedev/floppy.h +++ b/src/devices/imagedev/floppy.h @@ -56,17 +56,17 @@ public: u32 m_key; const char *m_description; - fs_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) : + fs_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) : m_manager(manager), m_type(type), m_image_size(image_size), m_name(name), - m_key(key), + m_key(0), m_description(description) {} - fs_info(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) : - m_manager(manager), + fs_info(const char *name, u32 key, const char *description) : + m_manager(nullptr), m_type(nullptr), m_image_size(0), m_name(name), @@ -80,7 +80,8 @@ public: void set_formats(std::function formats); floppy_image_format_t *get_formats() const; - const std::vector &get_fs() const { return m_fs; } + const std::vector &get_create_fs() const { return m_create_fs; } + const std::vector &get_io_fs() const { return m_io_fs; } floppy_image_format_t *get_load_format() const; floppy_image_format_t *identify(std::string filename); void set_rpm(float rpm); @@ -158,8 +159,8 @@ protected: floppy_image_device *m_fid; fs_enum(floppy_image_device *fid) : filesystem_manager_t::floppy_enumerator(), m_fid(fid) {}; - virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) override; - virtual void add_raw(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) override; + virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) override; + virtual void add_raw(const char *name, u32 key, const char *description) override; }; floppy_image_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -186,7 +187,7 @@ protected: std::unique_ptr image; char extension_list[256]; floppy_image_format_t *fif_list; - std::vector m_fs; + std::vector m_create_fs, m_io_fs; std::vector> m_fs_managers; emu_timer *index_timer; diff --git a/src/frontend/mame/ui/floppycntrl.cpp b/src/frontend/mame/ui/floppycntrl.cpp index e97151ebc4c..4fadfd00cd8 100644 --- a/src/frontend/mame/ui/floppycntrl.cpp +++ b/src/frontend/mame/ui/floppycntrl.cpp @@ -129,7 +129,7 @@ void menu_control_floppy_image::handle() m_state = START_FILE; handle(); } else { - const auto &fs = fd.get_fs(); + const auto &fs = fd.get_create_fs(); output_filename = util::zippath_combine(m_current_directory, m_current_file); output_format = format_array[m_submenu_result.i]; if(fs.size() == 1) { @@ -149,7 +149,7 @@ void menu_control_floppy_image::handle() m_state = START_FILE; handle(); } else { - create_fs = &fd.get_fs()[m_submenu_result.i]; + create_fs = &fd.get_create_fs()[m_submenu_result.i]; do_load_create(); stack_pop(); } diff --git a/src/lib/formats/all.cpp b/src/lib/formats/all.cpp index 5c3ee523508..0b50ddc9d69 100644 --- a/src/lib/formats/all.cpp +++ b/src/lib/formats/all.cpp @@ -457,6 +457,10 @@ #include "oric_tap.h" #endif +#ifdef HAS_FORMATS_FS_ORIC_JASMIN +#include "fs_oric_jasmin.h" +#endif + #ifdef HAS_FORMATS_IBMXDF_DSK #include "ibmxdf_dsk.h" #endif @@ -1130,6 +1134,10 @@ void mame_formats_full_list(mame_formats_enumerator &en) #endif #ifdef HAS_FORMATS_ORIC_DSK en.add(FLOPPY_ORIC_DSK_FORMAT); // oric_dsk.h + en.add(FLOPPY_ORIC_JASMIN_FORMAT); // oric_dsk.h +#endif +#ifdef HAS_FORMATS_FS_ORIC_JASMIN + en.add(FS_ORIC_JASMIN); // fs_oric_jasmin.h #endif en.category("Atari"); diff --git a/src/lib/formats/flopimg.cpp b/src/lib/formats/flopimg.cpp index a1bdfb83034..ba75a1ed7b8 100644 --- a/src/lib/formats/flopimg.cpp +++ b/src/lib/formats/flopimg.cpp @@ -936,6 +936,9 @@ void floppy_image::get_actual_geometry(int &_tracks, int &_heads) goto head_done; maxh--; } + else + maxh = -1; + head_done: _tracks = (maxt+4)/4; _heads = maxh+1; diff --git a/src/lib/formats/fs_oric_jasmin.cpp b/src/lib/formats/fs_oric_jasmin.cpp new file mode 100644 index 00000000000..13f70ecc258 --- /dev/null +++ b/src/lib/formats/fs_oric_jasmin.cpp @@ -0,0 +1,113 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +// Creation of Apple Oric_Jasmin floppy images + +#include "emu.h" +#include "fs_oric_jasmin.h" +#include "oric_dsk.h" + +// Floppy only, format is 41 tracks, 1/2 heads, 17 sectors. +// Filesystem has no subdirectories. +// +// References are pair of bytes (track + head*41, sector) +// +// Track 20 sector 1 has the free bitmap and the volume name +// +// offset 3*(track + head*41): bitmap from track, 24 bits LSB first, +// sector 1 in bit 16, sector 17 in bit 0. +// 0x01ffff is empty track. Special value +// 0x800000 marks a full track. +// offset f6-f7: 0x8080 +// offset f8-ff: volume name, padded with 0x20 +// +// +// Track 20 sector 2 has the first directory sector. +// Directory sector format: +// offset 00-01: reference to the sector, (0, 0) for the first one +// offset 02-03: reference to the next sector, (0, 0) on the first sector if it's the end, (ff, 00) for the end of another sector +// offset 04+ : 14 file entries, 18 bytes each +// offset 00-01: reference to the first sector of the inode, (ff, xx) when no entry +// offset 02 : U/L for (U)nlocked or (L)ocked file +// offset 03-0e: filename.ext, space padiing between filename and '.' +// offset 0f : S/D for (S)equential (normal) or (D)irect-access files +// offset 10-11: number of sectors used by the file, including inode, little-endian +// +// Inodes: +// offset 00-01: reference to the next inode sector, (ff, 00) on the last one +// offset 02-03: loading address for the file on the first sector, ffff otherwise +// offset 04-05: length of the file in bytes on the first sector, ffff otherwise +// offset 06+ : reference to data sectors, (ff, ff) when done + +void fs_oric_jasmin::enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector &variants) const +{ + if(has(form_factor, variants, floppy_image::FF_3, floppy_image::DSDD)) + fe.add(this, FLOPPY_ORIC_JASMIN_FORMAT, 356864, "oric_jasmin_ds", "Oric Jasmin dual-sided"); + if(has(form_factor, variants, floppy_image::FF_3, floppy_image::SSDD)) + fe.add(this, FLOPPY_ORIC_JASMIN_FORMAT, 178432, "oric_jasmin_ss", "Oric Jasmin single-sided"); +} + +std::unique_ptr fs_oric_jasmin::mount(fsblk_t &blockdev) const +{ + return std::make_unique(blockdev); +} + +bool fs_oric_jasmin::can_format() const +{ + return true; +} + +bool fs_oric_jasmin::can_read() const +{ + return false; +} + +bool fs_oric_jasmin::can_write() const +{ + return false; +} + + +void fs_oric_jasmin::impl::format() +{ + std::string volume_name = "UNTITLED"; + m_blockdev.set_block_size(256); + u32 blocks = m_blockdev.block_count(); + + m_blockdev.fill(0x6c); + + u32 bblk = 20*17; + auto fmap = m_blockdev.get(bblk); + u32 off = 0; + for(u32 blk = 0; blk != blocks; blk += 17) { + if(blk == bblk) { + fmap.w8(off , 0xff); + fmap.w8(off + 1, 0x7f); + fmap.w8(off + 2, 0x00); + } else { + fmap.w8(off , 0xff); + fmap.w8(off + 1, 0xff); + fmap.w8(off + 2, 0x01); + } + off += 3; + } + + for(u32 blk = blocks; blk != 17*42*2; blk += 17) { + fmap.w8(off , 0x00); + fmap.w8(off + 1, 0x00); + fmap.w8(off + 2, 0x80); + off += 3; + } + + fmap.w8(0xf6, 0x80); + fmap.w8(0xf7, 0x80); + fmap.fill(0xf8, 0x20, 8); + fmap.wstr(0xf8, volume_name); + + auto bdir = m_blockdev.get(20*17+1); + bdir.fill(0xff); + bdir.w16l(0, 0x0000); + bdir.w16l(2, 0x0000); +} + +const filesystem_manager_type FS_ORIC_JASMIN = &filesystem_manager_creator;; diff --git a/src/lib/formats/fs_oric_jasmin.h b/src/lib/formats/fs_oric_jasmin.h new file mode 100644 index 00000000000..f2f212b1065 --- /dev/null +++ b/src/lib/formats/fs_oric_jasmin.h @@ -0,0 +1,35 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +// Creation of Oric Jasmin floppy images + +#ifndef MAME_FORMATS_FS_ORIC_JASMIN_H +#define MAME_FORMATS_FS_ORIC_JASMIN_H + +#pragma once + +#include "fsmgr.h" + +class fs_oric_jasmin : public filesystem_manager_t { +public: + class impl : public filesystem_t { + public: + impl(fsblk_t &blockdev) : filesystem_t(blockdev) {} + virtual ~impl() = default; + + virtual void format() override; + }; + + fs_oric_jasmin() : filesystem_manager_t() {} + + virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector &variants) const override; + virtual std::unique_ptr mount(fsblk_t &blockdev) const override; + + virtual bool can_format() const override; + virtual bool can_read() const override; + virtual bool can_write() const override; +}; + +extern const filesystem_manager_type FS_ORIC_JASMIN; + +#endif diff --git a/src/lib/formats/fs_prodos.cpp b/src/lib/formats/fs_prodos.cpp index 820eb5bbf77..25e5cdc152f 100644 --- a/src/lib/formats/fs_prodos.cpp +++ b/src/lib/formats/fs_prodos.cpp @@ -7,7 +7,7 @@ #include "fs_prodos.h" #include "ap_dsk35.h" -const u8 fs_prodos::boot[512] = { +const u8 fs_prodos::impl::boot[512] = { 0x01, 0x38, 0xb0, 0x03, 0x4c, 0x1c, 0x09, 0x78, 0x86, 0x43, 0xc9, 0x03, 0x08, 0x8a, 0x29, 0x70, 0x4a, 0x4a, 0x4a, 0x4a, 0x09, 0xc0, 0x85, 0x49, 0xa0, 0xff, 0x84, 0x48, 0x28, 0xc8, 0xb1, 0x48, 0xd0, 0x3a, 0xb0, 0x0e, 0xa9, 0x03, 0x8d, 0x00, 0x08, 0xe6, 0x3d, 0xa5, 0x49, 0x48, 0xa9, 0x5b, @@ -44,49 +44,74 @@ const u8 fs_prodos::boot[512] = { void fs_prodos::enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector &variants) const { - bool all = form_factor == floppy_image::FF_UNKNOWN; - - if(all || (form_factor == floppy_image::FF_35 && has_variant(variants, floppy_image::DSDD))) - fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 819200, "prodos_800k", 800, "Apple ProDOS 800K"); - if(all || (form_factor == floppy_image::FF_35 && has_variant(variants, floppy_image::SSDD))) - fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 409600, "prodos_400k", 400, "Apple ProDOS 400K"); + if(has(form_factor, variants, floppy_image::FF_35, floppy_image::DSDD)) + fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 819200, "prodos_800k", "Apple ProDOS 800K"); + if(has(form_factor, variants, floppy_image::FF_35, floppy_image::SSDD)) + fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 409600, "prodos_400k", "Apple ProDOS 400K"); } -void fs_prodos::floppy_instantiate(u32 key, std::vector &image) const +std::unique_ptr fs_prodos::mount(fsblk_t &blockdev) const +{ + return std::make_unique(blockdev); +} + +bool fs_prodos::can_format() const +{ + return true; +} + +bool fs_prodos::can_read() const +{ + return false; +} + +bool fs_prodos::can_write() const +{ + return false; +} + +void fs_prodos::impl::format() { std::string volume_name = "UNTITLED"; - u32 blocks = key * 2; + m_blockdev.set_block_size(512); + u32 blocks = m_blockdev.block_count(); - copy(image, 0x000, boot, 0x200); // Standard ProDOS boot sector as written by a 2gs + m_blockdev.get(0).copy(0x000, boot, 0x200); // Standard ProDOS boot sector as written by a 2gs + m_blockdev.get(1).fill(0x00); // No SOS boot sector - fill(image, 0x200, 0x00, 0x200); // No SOS boot sector + auto kblk1 = m_blockdev.get(2); // key block first block + auto kblk2 = m_blockdev.get(3); // key block second block + auto kblk3 = m_blockdev.get(4); // key block third block + auto kblk4 = m_blockdev.get(5); // key block fourth block - w16l(image, 0x400, 0x0000); // Backwards key block pointer (null) - w16l(image, 0x402, 0x0003); // Forwards key block pointer - w8 (image, 0x404, 0xf0 | volume_name.size()); // Block type (f, key block) and name size - wstr(image, 0x405, volume_name); // Volume name, up to 15 characters - w32b(image, 0x416, 0x642a250d); // ??? date & time - w16b(image, 0x41a, 0x80ff); // ??? - w32b(image, 0x41c, 0x642a250d); // Creation date & time - w8 (image, 0x420, 0x05); // ProDOS version (2gs) - w8 (image, 0x421, 0x00); // ProDOS minimum version - w8 (image, 0x422, 0xc3); // Allowed access (destroy, rename, !backup, 3x0, write read) - w8 (image, 0x423, 0x27); // Directory entry length (fixed) - w8 (image, 0x424, 0x0d); // Entries per block (fixed) - w16l(image, 0x425, 0x0000); // Number of file entries in the directory - w16l(image, 0x427, 0x0006); // Bitmap block pointer - w16l(image, 0x429, blocks); // Number of blocks + kblk1.w16l(0x00, 0x0000); // Backwards key block pointer (null) + kblk1.w16l(0x02, 0x0003); // Forwards key block pointer + kblk1.w8 (0x04, 0xf0 | volume_name.size()); // Block type (f, key block) and name size + kblk1.wstr(0x05, volume_name); // Volume name, up to 15 characters + kblk1.w32b(0x16, 0x642a250d); // ??? date & time + kblk1.w16b(0x1a, 0x80ff); // ??? + kblk1.w32b(0x1c, 0x642a250d); // Creation date & time + kblk1.w8 (0x20, 0x05); // ProDOS version (2gs) + kblk1.w8 (0x21, 0x00); // ProDOS minimum version + kblk1.w8 (0x22, 0xc3); // Allowed access (destroy, rename, !backup, 3x0, write read) + kblk1.w8 (0x23, 0x27); // Directory entry length (fixed) + kblk1.w8 (0x24, 0x0d); // Entries per block (fixed) + kblk1.w16l(0x25, 0x0000); // Number of file entries in the directory + kblk1.w16l(0x27, 0x0006); // Bitmap block pointer + kblk1.w16l(0x29, blocks); // Number of blocks - w16l(image, 0x600, 0x0002); // Backwards block pointer of the second volume block - w16l(image, 0x602, 0x0004); // Forwards block pointer of the second volume block - w16l(image, 0x800, 0x0003); // Backwards block pointer of the third volume block - w16l(image, 0x802, 0x0005); // Forwards block pointer of the third volume block - w16l(image, 0xa00, 0x0004); // Backwards block pointer of the fourth volume block - w16l(image, 0xa02, 0x0000); // Forwards block pointer of the fourth volume block (nmull) + kblk2.w16l(0x00, 0x0002); // Backwards block pointer of the second volume block + kblk2.w16l(0x02, 0x0004); // Forwards block pointer of the second volume block + kblk3.w16l(0x00, 0x0003); // Backwards block pointer of the third volume block + kblk3.w16l(0x02, 0x0005); // Forwards block pointer of the third volume block + kblk4.w16l(0x00, 0x0004); // Backwards block pointer of the fourth volume block + kblk4.w16l(0x02, 0x0000); // Forwards block pointer of the fourth volume block (null) + auto fmap = m_blockdev.get(6); + u8 *fdata = fmap.data(); // Mark blocks 7 to max as free for(u32 i = 7; i != blocks; i++) - image[0xc00 + (i >> 3)] |= 0x80 >> (i & 7); + fdata[i >> 3] |= 0x80 >> (i & 7); } const filesystem_manager_type FS_PRODOS = &filesystem_manager_creator;; diff --git a/src/lib/formats/fs_prodos.h b/src/lib/formats/fs_prodos.h index 5c9dfb3f082..75cb49f2507 100644 --- a/src/lib/formats/fs_prodos.h +++ b/src/lib/formats/fs_prodos.h @@ -12,13 +12,25 @@ class fs_prodos : public filesystem_manager_t { public: + class impl : public filesystem_t { + public: + impl(fsblk_t &blockdev) : filesystem_t(blockdev) {} + virtual ~impl() = default; + + virtual void format() override; + + private: + static const u8 boot[512]; + }; + fs_prodos() : filesystem_manager_t() {} virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector &variants) const override; - virtual void floppy_instantiate(u32 key, std::vector &image) const override; + virtual std::unique_ptr mount(fsblk_t &blockdev) const override; -private: - static const u8 boot[512]; + virtual bool can_format() const override; + virtual bool can_read() const override; + virtual bool can_write() const override; }; extern const filesystem_manager_type FS_PRODOS; diff --git a/src/lib/formats/fs_unformatted.cpp b/src/lib/formats/fs_unformatted.cpp index 0ce556fbab3..01e611557b6 100644 --- a/src/lib/formats/fs_unformatted.cpp +++ b/src/lib/formats/fs_unformatted.cpp @@ -35,43 +35,43 @@ void fs_unformatted::enumerate(floppy_enumerator &fe, uint32_t form_factor, cons : FSI_NONE; if(all || best_8 == FSI_8_DSDD) - fe.add_raw(this, "u8dsdd", FSI_8_DSDD, "Unformatted 8\" double-sided double-density"); + fe.add_raw("u8dsdd", FSI_8_DSDD, "Unformatted 8\" double-sided double-density"); if(all || best_8 == FSI_8_DSSD) - fe.add_raw(this, "u8dssd", FSI_8_DSSD, "Unformatted 8\" double-sided single-density"); + fe.add_raw("u8dssd", FSI_8_DSSD, "Unformatted 8\" double-sided single-density"); if(all || best_8 == FSI_8_SSSD) - fe.add_raw(this, "u8sssd", FSI_8_SSSD, "Unformatted 8\" single-sided single-density"); + fe.add_raw("u8sssd", FSI_8_SSSD, "Unformatted 8\" single-sided single-density"); if(all || best_525 == FSI_525_DSHD) - fe.add_raw(this, "u525dshd", FSI_525_DSHD, "Unformatted 5\"25 double-sided high-density"); + fe.add_raw("u525dshd", FSI_525_DSHD, "Unformatted 5\"25 double-sided high-density"); if(all || best_525 == FSI_525_DSQD) - fe.add_raw(this, "u525dsqd", FSI_525_DSQD, "Unformatted 5\"25 double-sided quad-density"); + fe.add_raw("u525dsqd", FSI_525_DSQD, "Unformatted 5\"25 double-sided quad-density"); if(all || best_525 == FSI_525_DSDD) - fe.add_raw(this, "u525dsdd", FSI_525_DSDD, "Unformatted 5\"25 double-sided double-density"); + fe.add_raw("u525dsdd", FSI_525_DSDD, "Unformatted 5\"25 double-sided double-density"); if(all) - fe.add_raw(this, "u525dssd", FSI_525_DSSD, "Unformatted 5\"25 double-sided single-density"); + fe.add_raw("u525dssd", FSI_525_DSSD, "Unformatted 5\"25 double-sided single-density"); if(all || best_525 == FSI_525_SSQD) - fe.add_raw(this, "u525ssqd", FSI_525_SSQD, "Unformatted 5\"25 single-sided quad-density"); + fe.add_raw("u525ssqd", FSI_525_SSQD, "Unformatted 5\"25 single-sided quad-density"); if(all || best_525 == FSI_525_SSDD) - fe.add_raw(this, "u525ssdd", FSI_525_SSDD, "Unformatted 5\"25 single-sided double-density"); + fe.add_raw("u525ssdd", FSI_525_SSDD, "Unformatted 5\"25 single-sided double-density"); if(all || best_525 == FSI_525_SSSD) - fe.add_raw(this, "u525sssd", FSI_525_SSSD, "Unformatted 5\"25 single-sided single-density"); + fe.add_raw("u525sssd", FSI_525_SSSD, "Unformatted 5\"25 single-sided single-density"); if(all || has_variant(variants, floppy_image::DSED)) - fe.add_raw(this, "u35dsed", FSI_35_DSED, "Unformatted 3\"5 double-sided extra-density"); + fe.add_raw("u35dsed", FSI_35_DSED, "Unformatted 3\"5 double-sided extra-density"); if(all || has_variant(variants, floppy_image::DSHD)) - fe.add_raw(this, "u35dshd", FSI_35_DSHD, "Unformatted 3\"5 double-sided high-density"); + fe.add_raw("u35dshd", FSI_35_DSHD, "Unformatted 3\"5 double-sided high-density"); if(all || best_35 == FSI_35_DSDD) - fe.add_raw(this, "u35dsdd", FSI_35_DSDD, "Unformatted 3\"5 double-sided double-density"); + fe.add_raw("u35dsdd", FSI_35_DSDD, "Unformatted 3\"5 double-sided double-density"); if(all || best_35 == FSI_35_SSDD) - fe.add_raw(this, "u35ssdd", FSI_35_SSDD, "Unformatted 3\"5 single-sided double-density"); + fe.add_raw("u35ssdd", FSI_35_SSDD, "Unformatted 3\"5 single-sided double-density"); if(all || best_3 == FSI_3_DSDD) - fe.add_raw(this, "u3dsdd", FSI_35_DSDD, "Unformatted 3\" double-sided double-density"); + fe.add_raw("u3dsdd", FSI_35_DSDD, "Unformatted 3\" double-sided double-density"); if(all || best_3 == FSI_3_SSDD) - fe.add_raw(this, "u3ssdd", FSI_35_SSDD, "Unformatted 3\" single-sided double-density"); + fe.add_raw("u3ssdd", FSI_35_SSDD, "Unformatted 3\" single-sided double-density"); } -void fs_unformatted::floppy_instantiate_raw(u32 key, floppy_image *image) const +void fs_unformatted::format(u32 key, floppy_image *image) { switch(key) { case FSI_8_DSDD: image->set_form_variant(floppy_image::FF_8, floppy_image::DSDD); break; @@ -96,4 +96,24 @@ void fs_unformatted::floppy_instantiate_raw(u32 key, floppy_image *image) const } } +std::unique_ptr fs_unformatted::mount(fsblk_t &blockdev) const +{ + return nullptr; +} + +bool fs_unformatted::can_format() const +{ + return false; +} + +bool fs_unformatted::can_read() const +{ + return false; +} + +bool fs_unformatted::can_write() const +{ + return false; +} + const filesystem_manager_type FS_UNFORMATTED = &filesystem_manager_creator; diff --git a/src/lib/formats/fs_unformatted.h b/src/lib/formats/fs_unformatted.h index 5bcaaf1e34e..b21ed311054 100644 --- a/src/lib/formats/fs_unformatted.h +++ b/src/lib/formats/fs_unformatted.h @@ -12,12 +12,6 @@ class fs_unformatted : public filesystem_manager_t { public: - fs_unformatted() : filesystem_manager_t() {} - - virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector &variants) const override; - virtual void floppy_instantiate_raw(u32 key, floppy_image *image) const override; - -private: enum { FSI_NONE, @@ -41,6 +35,17 @@ private: FSI_3_DSDD, FSI_3_SSDD, }; + + fs_unformatted() : filesystem_manager_t() {} + + static void format(u32 key, floppy_image *image); + + virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector &variants) const override; + virtual std::unique_ptr mount(fsblk_t &blockdev) const override; + + virtual bool can_format() const override; + virtual bool can_read() const override; + virtual bool can_write() const override; }; extern const filesystem_manager_type FS_UNFORMATTED; diff --git a/src/lib/formats/fsblk_vec.cpp b/src/lib/formats/fsblk_vec.cpp new file mode 100644 index 00000000000..a1f38898bcb --- /dev/null +++ b/src/lib/formats/fsblk_vec.cpp @@ -0,0 +1,39 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +// Block device on vector + +#include "emu.h" +#include "fsblk_vec.h" + +const uint8_t *fsblk_vec_t::blk_t::rodata() +{ + return m_data; +} + +uint8_t *fsblk_vec_t::blk_t::data() +{ + return m_data; +} + +void fsblk_vec_t::blk_t::drop_weak_references() +{ +} + +uint32_t fsblk_vec_t::block_count() const +{ + return m_data.size() / m_block_size; +} + +fsblk_t::block_t fsblk_vec_t::get(uint32_t id) +{ + if(id >= block_count()) + fatalerror("Block number overflow: requiring block %d on device of size %d (%d bytes, block size %d)\n", id, block_count(), m_data.size(), m_block_size); + return block_t(new blk_t(m_data.data() + m_block_size*id, m_block_size)); +} + +void fsblk_vec_t::fill(uint8_t data) +{ + std::fill(m_data.begin(), m_data.end(), data); +} + diff --git a/src/lib/formats/fsblk_vec.h b/src/lib/formats/fsblk_vec.h new file mode 100644 index 00000000000..b663d673855 --- /dev/null +++ b/src/lib/formats/fsblk_vec.h @@ -0,0 +1,33 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +// Block device on vector + +#include "fsmgr.h" + +class fsblk_vec_t : public fsblk_t { +private: + class blk_t : public iblock_t { + public: + blk_t(uint8_t *data, uint32_t size) : iblock_t(size), m_data(data) {} + virtual ~blk_t() = default; + + virtual const uint8_t *rodata() override; + virtual uint8_t *data() override; + virtual void drop_weak_references() override; + + private: + uint8_t *m_data; + }; + +public: + fsblk_vec_t(std::vector &data) : m_data(data) {} + virtual ~fsblk_vec_t() = default; + + virtual uint32_t block_count() const override; + virtual block_t get(uint32_t id) override; + virtual void fill(uint8_t data) override; + +private: + std::vector &m_data; +}; diff --git a/src/lib/formats/fsmgr.cpp b/src/lib/formats/fsmgr.cpp index 597d1428411..ec80710ac33 100644 --- a/src/lib/formats/fsmgr.cpp +++ b/src/lib/formats/fsmgr.cpp @@ -8,20 +8,47 @@ #include "emu.h" #include "fsmgr.h" +void fsblk_t::iblock_t::ref() +{ + m_ref ++; +} + +void fsblk_t::iblock_t::ref_weak() +{ + m_weak_ref ++; +} + +void fsblk_t::iblock_t::unref() +{ + m_ref --; + if(m_ref == 0) { + if(m_weak_ref) { + drop_weak_references(); + if(m_weak_ref) + fatalerror("drop_weak_references kept %d active references\n", m_weak_ref); + } else + delete this; + } +} + +void fsblk_t::iblock_t::unref_weak() +{ + m_weak_ref --; + if(m_weak_ref == 0 && m_ref == 0) + delete this; +} + + void filesystem_manager_t::enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector &variants) const { } -void filesystem_manager_t::floppy_instantiate(u32 key, std::vector &image) const +void filesystem_manager_t::enumerate(hd_enumerator &he) const { - fprintf(stderr, "filesystem_manager_t::floppy_instantiate called while unsupported\n"); - abort(); } -void filesystem_manager_t::floppy_instantiate_raw(u32 key, floppy_image *image) const +void filesystem_manager_t::enumerate(cdrom_enumerator &ce) const { - fprintf(stderr, "filesystem_manager_t::floppy_instantiate_raw called while unsupported\n"); - abort(); } bool filesystem_manager_t::has_variant(const std::vector &variants, uint32_t variant) @@ -32,50 +59,99 @@ bool filesystem_manager_t::has_variant(const std::vector &variants, ui return false; } -void filesystem_manager_t::copy(std::vector &image, u32 offset, const u8 *src, u32 size) +bool filesystem_manager_t::has(uint32_t form_factor, const std::vector &variants, uint32_t ff, uint32_t variant) { - memcpy(image.data() + offset, src, size); + if(form_factor == floppy_image::FF_UNKNOWN) + return true; + if(form_factor != ff) + return false; + for(uint32_t v : variants) + if(variant == v) + return true; + return false; } -void filesystem_manager_t::fill(std::vector &image, u32 offset, u8 data, u32 size) +void filesystem_t::format() { - memset(image.data() + offset, data, size); + fatalerror("format called on filesystem not supporting it.\n"); } -void filesystem_manager_t::wstr(std::vector &image, u32 offset, const std::string &str) +filesystem_t::dir_t filesystem_t::root() { - memcpy(image.data() + offset, str.data(), str.size()); + fatalerror("root called on filesystem not supporting it.\n"); } -void filesystem_manager_t::w8(std::vector &image, u32 offset, u8 data) +void fsblk_t::set_block_size(uint32_t block_size) { - image[offset] = data; + m_block_size = block_size; } -void filesystem_manager_t::w16b(std::vector &image, u32 offset, u16 data) + +uint8_t *fsblk_t::iblock_t::offset(const char *function, uint32_t off, uint32_t size) { - image[offset ] = data >> 8; - image[offset+1] = data; + if(off + size > m_size) + fatalerror("block_t::%s out-of-block access, offset=%d, size=%d, block size=%d\n", function, off, size, m_size); + return data() + off; } -void filesystem_manager_t::w32b(std::vector &image, u32 offset, u32 data) +void fsblk_t::block_t::copy(u32 offset, const uint8_t *src, u32 size) { - image[offset ] = data >> 24; - image[offset+1] = data >> 16; - image[offset+2] = data >> 8; - image[offset+3] = data; + uint8_t *blk = m_block->offset("copy", offset, size); + memcpy(blk, src, size); } -void filesystem_manager_t::w16l(std::vector &image, u32 offset, u16 data) +void fsblk_t::block_t::fill(u32 offset, uint8_t data, u32 size) { - image[offset ] = data; - image[offset+1] = data >> 8; + uint8_t *blk = m_block->offset("fill", offset, size); + memset(blk, data, size); } -void filesystem_manager_t::w32l(std::vector &image, u32 offset, u32 data) +void fsblk_t::block_t::fill(uint8_t data) { - image[offset ] = data; - image[offset+1] = data >> 8; - image[offset+2] = data >> 16; - image[offset+3] = data >> 24; + uint8_t *blk = m_block->data(); + memset(blk, data, m_block->size()); +} + +void fsblk_t::block_t::wstr(u32 offset, const std::string &str) +{ + uint8_t *blk = m_block->offset("wstr", offset, str.size()); + memcpy(blk, str.data(), str.size()); +} + +void fsblk_t::block_t::w8(u32 offset, uint8_t data) +{ + uint8_t *blk = m_block->offset("w8", offset, 1); + blk[0] = data; +} + +void fsblk_t::block_t::w16b(u32 offset, u16 data) +{ + uint8_t *blk = m_block->offset("w16b", offset, 2); + blk[0] = data >> 8; + blk[1] = data; +} + +void fsblk_t::block_t::w32b(u32 offset, u32 data) +{ + uint8_t *blk = m_block->offset("w32b", offset, 4); + blk[0] = data >> 24; + blk[1] = data >> 16; + blk[2] = data >> 8; + blk[3] = data; +} + +void fsblk_t::block_t::w16l(u32 offset, u16 data) +{ + uint8_t *blk = m_block->offset("w16l", offset, 2); + blk[0] = data; + blk[1] = data >> 8; +} + +void fsblk_t::block_t::w32l(u32 offset, u32 data) +{ + uint8_t *blk = m_block->offset("w32l", offset, 4); + blk[0] = data; + blk[1] = data >> 8; + blk[2] = data >> 16; + blk[3] = data >> 24; } diff --git a/src/lib/formats/fsmgr.h b/src/lib/formats/fsmgr.h index 8cf082bb2ec..46a9f285c5e 100644 --- a/src/lib/formats/fsmgr.h +++ b/src/lib/formats/fsmgr.h @@ -1,9 +1,7 @@ // license:BSD-3-Clause // copyright-holders:Olivier Galibert -// Filesystem management code for floppy and hd images - -// Currently limited to floppies and creation of preformatted images +// Filesystem management code for floppy, hd and cdrom images #ifndef MAME_FORMATS_FSMGR_H #define MAME_FORMATS_FSMGR_H @@ -12,38 +10,322 @@ #include "flopimg.h" +class fsblk_t { +protected: + class iblock_t { + public: + iblock_t(uint32_t size) : m_ref(0), m_weak_ref(0), m_size(size) {} + virtual ~iblock_t() = default; + + void ref(); + void ref_weak(); + void unref(); + void unref_weak(); + + uint32_t size() const { return m_size; } + + virtual void drop_weak_references() = 0; + + virtual const uint8_t *rodata() = 0; + virtual uint8_t *data() = 0; + uint8_t *offset(const char *function, uint32_t off, uint32_t size); + + protected: + uint32_t m_ref, m_weak_ref; + uint32_t m_size; + }; + + +public: + class block_t { + public: + block_t(iblock_t *block, bool weak = false) : m_block(block), m_is_weak_ref(weak) { + ref(); + } + + block_t(const block_t &cref) { + m_block = cref.m_block; + m_is_weak_ref = cref.m_is_weak_ref; + ref(); + } + + block_t(block_t &&cref) { + m_block = cref.m_block; + m_is_weak_ref = cref.m_is_weak_ref; + cref.m_block = nullptr; + } + + ~block_t() { + unref(); + } + + block_t &operator =(const block_t &cref) { + m_block = cref.m_block; + m_is_weak_ref = cref.m_is_weak_ref; + ref(); + return *this; + } + + block_t &operator =(block_t &&cref) { + m_block = cref.m_block; + m_is_weak_ref = cref.m_is_weak_ref; + cref.m_block = nullptr; + return *this; + } + + const uint8_t *rodata() { + return m_block ? m_block->rodata() : nullptr; + } + + uint8_t *data() { + return m_block ? m_block->data() : nullptr; + } + + void copy(uint32_t offset, const uint8_t *src, uint32_t size); + void fill( uint8_t data); + void fill(uint32_t offset, uint8_t data, uint32_t size); + void wstr(uint32_t offset, const std::string &str); + void w8( uint32_t offset, uint8_t data); + void w16b(uint32_t offset, u16 data); + void w32b(uint32_t offset, uint32_t data); + void w16l(uint32_t offset, u16 data); + void w32l(uint32_t offset, uint32_t data); + + private: + iblock_t *m_block; + bool m_is_weak_ref; + + void ref() { + if(m_block) { + if(m_is_weak_ref) + m_block->ref_weak(); + else + m_block->ref(); + } + } + + void unref() { + if(m_block) { + if(m_is_weak_ref) + m_block->unref_weak(); + else + m_block->unref(); + } + } + }; + + fsblk_t() = default; + virtual ~fsblk_t() = default; + + virtual void set_block_size(uint32_t block_size); + virtual uint32_t block_count() const = 0; + virtual block_t get(uint32_t id) = 0; + virtual void fill(uint8_t data) = 0; + +protected: + uint32_t m_block_size; +}; + + +class filesystem_t { +protected: + class idir_t { + public: + virtual ~idir_t(); + + void ref(); + void ref_weak(); + void unref(); + void unref_weak(); + + virtual void drop_weak_references(); + }; + + class ifile_t { + public: + virtual ~ifile_t(); + + void ref(); + void ref_weak(); + void unref(); + void unref_weak(); + + virtual void drop_weak_references(); + }; + +public: + class dir_t { + public: + dir_t(idir_t *dir, bool weak = false) : m_dir(dir), m_is_weak_ref(weak) { + ref(); + } + + dir_t(const dir_t &cref) { + m_dir = cref.m_dir; + m_is_weak_ref = cref.m_is_weak_ref; + ref(); + } + + dir_t(dir_t &&cref) { + m_dir = cref.m_dir; + m_is_weak_ref = cref.m_is_weak_ref; + cref.m_dir = nullptr; + } + + ~dir_t() { + unref(); + } + + dir_t &operator =(const dir_t &cref) { + m_dir = cref.m_dir; + m_is_weak_ref = cref.m_is_weak_ref; + ref(); + return *this; + } + + dir_t &operator =(dir_t &&cref) { + m_dir = cref.m_dir; + m_is_weak_ref = cref.m_is_weak_ref; + cref.m_dir = nullptr; + return *this; + } + + private: + idir_t *m_dir; + bool m_is_weak_ref; + + void ref() { + if(m_dir) { + if(m_is_weak_ref) + m_dir->ref_weak(); + else + m_dir->ref(); + } + } + + void unref() { + if(m_dir) { + if(m_is_weak_ref) + m_dir->unref_weak(); + else + m_dir->unref(); + } + } + }; + + class file_t { + public: + file_t(ifile_t *file, bool weak = false) : m_file(file), m_is_weak_ref(weak) { + ref(); + } + + file_t(const file_t &cref) { + m_file = cref.m_file; + m_is_weak_ref = cref.m_is_weak_ref; + ref(); + } + + file_t(file_t &&cref) { + m_file = cref.m_file; + m_is_weak_ref = cref.m_is_weak_ref; + cref.m_file = nullptr; + } + + ~file_t() { + unref(); + } + + file_t &operator =(const file_t &cref) { + m_file = cref.m_file; + m_is_weak_ref = cref.m_is_weak_ref; + ref(); + return *this; + } + + file_t &operator =(file_t &&cref) { + m_file = cref.m_file; + m_is_weak_ref = cref.m_is_weak_ref; + cref.m_file = nullptr; + return *this; + } + + private: + ifile_t *m_file; + bool m_is_weak_ref; + + void ref() { + if(m_file) { + if(m_is_weak_ref) + m_file->ref_weak(); + else + m_file->ref(); + } + } + + void unref() { + if(m_file) { + if(m_is_weak_ref) + m_file->unref_weak(); + else + m_file->unref(); + } + } + }; + + filesystem_t(fsblk_t &blockdev) : m_blockdev(blockdev) {} + + virtual ~filesystem_t() = default; + + virtual void format(); + virtual dir_t root(); + + +protected: + fsblk_t &m_blockdev; +}; + +class unformatted_floppy_creator; + class filesystem_manager_t { public: struct floppy_enumerator { virtual ~floppy_enumerator() = default; - virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) = 0; - virtual void add_raw(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) = 0; + virtual void add(const filesystem_manager_t *manager, floppy_format_type type, uint32_t image_size, const char *name, const char *description) = 0; + virtual void add_raw(const char *name, uint32_t key, const char *description) = 0; }; + struct hd_enumerator { + virtual ~hd_enumerator() = default; + + virtual void add(const filesystem_manager_t *manager, const char *name, const char *description) = 0; + }; + + struct cdrom_enumerator { + virtual ~cdrom_enumerator() = default; + + virtual void add(const filesystem_manager_t *manager, const char *name, const char *description) = 0; + }; + + virtual ~filesystem_manager_t() = default; virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector &variants) const; + virtual void enumerate(hd_enumerator &he) const; + virtual void enumerate(cdrom_enumerator &ce) const; - // Floppy image initialization - virtual void floppy_instantiate(u32 key, std::vector &image) const; + virtual bool can_format() const = 0; + virtual bool can_read() const = 0; + virtual bool can_write() const = 0; - // Floppy image initialization for add_raw - virtual void floppy_instantiate_raw(u32 key, floppy_image *image) const; + // Create a filesystem object from a block device + virtual std::unique_ptr mount(fsblk_t &blockdev) const = 0; protected: filesystem_manager_t() = default; + static bool has(uint32_t form_factor, const std::vector &variants, uint32_t ff, uint32_t variant); static bool has_variant(const std::vector &variants, uint32_t variant); - - static void copy(std::vector &image, u32 offset, const u8 *src, u32 size); - static void fill(std::vector &image, u32 offset, u8 data, u32 size); - static void wstr(std::vector &image, u32 offset, const std::string &str); - static void w8(std::vector &image, u32 offset, u8 data); - static void w16b(std::vector &image, u32 offset, u16 data); - static void w32b(std::vector &image, u32 offset, u32 data); - static void w16l(std::vector &image, u32 offset, u16 data); - static void w32l(std::vector &image, u32 offset, u32 data); }; diff --git a/src/lib/formats/oric_dsk.cpp b/src/lib/formats/oric_dsk.cpp index f555416a21c..22d70124572 100644 --- a/src/lib/formats/oric_dsk.cpp +++ b/src/lib/formats/oric_dsk.cpp @@ -11,10 +11,6 @@ #include "formats/oric_dsk.h" -oric_dsk_format::oric_dsk_format() -{ -} - const char *oric_dsk_format::name() const { return "oric_dsk"; @@ -109,3 +105,97 @@ bool oric_dsk_format::save(io_generic *io, const std::vector &variants } const floppy_format_type FLOPPY_ORIC_DSK_FORMAT = &floppy_image_format_creator; + + +const char *oric_jasmin_format::name() const +{ + return "oric_jasmin"; +} + +const char *oric_jasmin_format::description() const +{ + return "Oric Jasmin pure sector image"; +} + +const char *oric_jasmin_format::extensions() const +{ + return "dsk"; +} + +bool oric_jasmin_format::supports_save() const +{ + return true; +} + +int oric_jasmin_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +{ + int size = io_generic_size(io); + bool can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD); + if(size == 41*17*256 || (can_ds && size == 41*17*256*2)) + return 50; + + return 0; +} + +bool oric_jasmin_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +{ + int size = io_generic_size(io); + bool can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD); + + if(size != 41*17*256 && (!can_ds || size != 41*17*256*2)) + return false; + + int heads = size == 41*17*256 ? 1 : 2; + + std::vector data(size); + io_generic_read(io, data.data(), 0, size); + + for(int head = 0; head != heads; head++) + for(int track = 0; track != 41; track++) { + desc_pc_sector sdesc[17]; + for(int s = 0; s != 17; s++) { + int sector = (s + 6*(track+1)) % 17; + sdesc[s].track = track; + sdesc[s].head = head; + sdesc[s].sector = sector + 1; + sdesc[s].size = 1; + sdesc[s].actual_size = 256; + sdesc[s].data = data.data() + 256 * (sector + track*17 + head*17*41); + sdesc[s].deleted = false; + sdesc[s].bad_crc = false; + } + + build_wd_track_mfm(track, head, image, 100000, 17, sdesc, 38, 40); + } + + image->set_form_variant(floppy_image::FF_3, heads == 2 ? floppy_image::DSDD : floppy_image::SSDD); + + return true; +} + +bool oric_jasmin_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +{ + int tracks, heads; + image->get_actual_geometry(tracks, heads); + + bool can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD); + if(heads == 2 && !can_ds) + return false; + if(heads == 0) + heads = 1; + + uint8_t zero[256]; + memset(zero, 0, 256); + + for(int head = 0; head != heads; head++) + for(int track = 0; track != 41; track++) { + auto sectors = extract_sectors_from_bitstream_mfm_pc(generate_bitstream_from_track(track, head, 2000, image)); + for(unsigned int sector = 0; sector != 17; sector ++) { + const uint8_t *data = sector+1 < sectors.size() && !sectors[sector+1].empty() ? sectors[sector+1].data() : zero; + io_generic_write(io, data, 256 * (sector + track*17 + head*17*41), 256); + } + } + return true; +} + +const floppy_format_type FLOPPY_ORIC_JASMIN_FORMAT = &floppy_image_format_creator; diff --git a/src/lib/formats/oric_dsk.h b/src/lib/formats/oric_dsk.h index 1c9e12a29d6..e42b876e52f 100644 --- a/src/lib/formats/oric_dsk.h +++ b/src/lib/formats/oric_dsk.h @@ -17,7 +17,7 @@ class oric_dsk_format : public floppy_image_format_t { public: - oric_dsk_format(); + oric_dsk_format() = default; virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; @@ -30,4 +30,21 @@ public: extern const floppy_format_type FLOPPY_ORIC_DSK_FORMAT; +class oric_jasmin_format : public floppy_image_format_t +{ +public: + oric_jasmin_format() = default; + + virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + + virtual const char *name() const override; + virtual const char *description() const override; + virtual const char *extensions() const override; + virtual bool supports_save() const override; +}; + +extern const floppy_format_type FLOPPY_ORIC_JASMIN_FORMAT; + #endif // MAME_FORMATS_ORIC_DSK_H diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp index 5eac3a42fc8..1e833a54b6b 100644 --- a/src/tools/floptool.cpp +++ b/src/tools/floptool.cpp @@ -19,6 +19,7 @@ #include #include +#include "../emu/emucore.h" #include "corestr.h" #include "osdcomm.h" @@ -27,6 +28,19 @@ using u16 = uint16_t; using u32 = uint32_t; #include "formats/all.h" +#include "formats/fs_unformatted.h" +#include "formats/fsblk_vec.h" + +emu_fatalerror::emu_fatalerror(util::format_argument_pack const &args) + : emu_fatalerror(0, args) +{ +} + +emu_fatalerror::emu_fatalerror(int _exitcode, util::format_argument_pack const &args) + : m_text(util::string_format(args)) + , m_code(_exitcode) +{ +} struct fs_info { const filesystem_manager_t *m_manager; @@ -36,17 +50,17 @@ struct fs_info { u32 m_key; const char *m_description; - fs_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) : + fs_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) : m_manager(manager), m_type(type), m_image_size(image_size), m_name(name), - m_key(key), + m_key(0), m_description(description) {} - fs_info(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) : - m_manager(manager), + fs_info(const char *name, u32 key, const char *description) : + m_manager(nullptr), m_type(nullptr), m_image_size(0), m_name(name), @@ -133,8 +147,8 @@ struct fs_enum : public filesystem_manager_t::floppy_enumerator { fs_enum(enumerator *en) : filesystem_manager_t::floppy_enumerator(), m_en(en) {}; void reg(const fs_info &fsi) const; - virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) override; - virtual void add_raw(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) override; + virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) override; + virtual void add_raw(const char *name, u32 key, const char *description) override; }; struct enumerator : public mame_formats_enumerator { @@ -193,15 +207,15 @@ void fs_enum::reg(const fs_info &fsi) const fs_by_key.emplace(key, fsi); } -void fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) +void fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) { - fs_info fsi(manager, type, image_size, name, key, description); + fs_info fsi(manager, type, image_size, name, description); reg(fsi); } -void fs_enum::add_raw(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) +void fs_enum::add_raw(const char *name, u32 key, const char *description) { - fs_info fsi(manager, name, key, description); + fs_info fsi(name, key, description); reg(fsi); } @@ -280,7 +294,7 @@ static void display_formats() if(!e.second.empty()) { fprintf(stderr, "%s:\n", e.first.c_str()); for(floppy_image_format_t *fif : e.second) - fprintf(stderr, " %-*s - %s [%s]\n", sk, fif->name(), fif->description(), fif->extensions()); + fprintf(stderr, " %-*s - %s [%s]\n", sk, fif->name(), fif->description(), fif->extensions()); } fprintf(stderr, "\n\n"); @@ -289,7 +303,13 @@ static void display_formats() if(!e.second.empty()) { fprintf(stderr, "%s:\n", e.first.c_str()); for(const fs_info &fs : e.second) - fprintf(stderr, " %-*s - %s\n", sk, fs.m_name, fs.m_description); + fprintf(stderr, " %-*s %c%c%c - %s\n", + sk, + fs.m_name, + !fs.m_manager || fs.m_manager->can_format() ? 'f' : '-', + fs.m_manager && fs.m_manager->can_read() ? 'r' : '-', + fs.m_manager && fs.m_manager->can_write() ? 'w' : '-', + fs.m_description); } } @@ -435,7 +455,10 @@ static int create(int argc, char *argv[]) if(source_fs->m_type) { std::vector img(source_fs->m_image_size); - source_fs->m_manager->floppy_instantiate(source_fs->m_key, img); + fsblk_vec_t blockdev(img); + auto fs = source_fs->m_manager->mount(blockdev); + fs->format(); + auto iog = ram_open(img); auto source_format = source_fs->m_type(); source_format->load(iog, floppy_image::FF_UNKNOWN, variants, &image); @@ -443,7 +466,7 @@ static int create(int argc, char *argv[]) delete iog; } else - source_fs->m_manager->floppy_instantiate_raw(source_fs->m_key, &image); + fs_unformatted::format(source_fs->m_key, &image); char msg[4096]; sprintf(msg, "Error opening %s for writing", argv[4]);