mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
reorganize the floptool code, add some write support
This commit is contained in:
parent
9508ac0530
commit
da1bd3b0ec
@ -609,6 +609,8 @@ includedirs {
|
||||
}
|
||||
|
||||
files {
|
||||
MAME_DIR .. "src/tools/image_handler.cpp",
|
||||
MAME_DIR .. "src/tools/image_handler.h",
|
||||
MAME_DIR .. "src/tools/floptool.cpp",
|
||||
}
|
||||
|
||||
|
@ -177,9 +177,9 @@ void format_registration::add(floppy_format_type format)
|
||||
m_formats.push_back(format);
|
||||
}
|
||||
|
||||
void format_registration::add(filesystem_manager_type fs)
|
||||
void format_registration::add(const filesystem_manager_t &fs)
|
||||
{
|
||||
m_fs.push_back(fs);
|
||||
m_fs.push_back(&fs);
|
||||
}
|
||||
|
||||
void floppy_image_device::default_fm_floppy_formats(format_registration &fr)
|
||||
@ -311,12 +311,12 @@ 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, const char *description)
|
||||
void floppy_image_device::fs_enum::add(floppy_format_type type, u32 image_size, const char *name, const char *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));
|
||||
if(m_manager->can_format())
|
||||
m_fid->m_create_fs.emplace_back(fs_info(m_manager, type, image_size, name, description));
|
||||
if(m_manager->can_read())
|
||||
m_fid->m_io_fs.emplace_back(fs_info(m_manager, type, image_size, name, description));
|
||||
}
|
||||
|
||||
void floppy_image_device::fs_enum::add_raw(const char *name, u32 key, const char *description)
|
||||
@ -347,11 +347,11 @@ void floppy_image_device::register_formats()
|
||||
}
|
||||
|
||||
fs_enum fse(this);
|
||||
for(filesystem_manager_type fmt : fr.m_fs)
|
||||
for(const filesystem_manager_t *fmt : fr.m_fs)
|
||||
{
|
||||
auto ff = fmt();
|
||||
ff->enumerate_f(fse, form_factor, variants);
|
||||
m_fs_managers.push_back(std::unique_ptr<filesystem_manager_t>(ff));
|
||||
fse.m_manager = fmt;
|
||||
fmt->enumerate_f(fse, form_factor, variants);
|
||||
m_fs_managers.push_back(fmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,14 +27,14 @@ public:
|
||||
format_registration();
|
||||
|
||||
void add(floppy_format_type format);
|
||||
void add(filesystem_manager_type fs);
|
||||
void add(const filesystem_manager_t &fs);
|
||||
|
||||
void add_fm_containers();
|
||||
void add_mfm_containers();
|
||||
void add_pc_formats();
|
||||
|
||||
std::vector<floppy_format_type> m_formats;
|
||||
std::vector<filesystem_manager_type> m_fs;
|
||||
std::vector<const filesystem_manager_t *> m_fs;
|
||||
};
|
||||
|
||||
class floppy_image_device : public device_t,
|
||||
@ -157,9 +157,11 @@ public:
|
||||
protected:
|
||||
struct fs_enum : public filesystem_manager_t::floppy_enumerator {
|
||||
floppy_image_device *m_fid;
|
||||
const filesystem_manager_t *m_manager;
|
||||
|
||||
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, const char *description) override;
|
||||
virtual void add(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;
|
||||
};
|
||||
|
||||
@ -188,7 +190,7 @@ protected:
|
||||
char extension_list[256];
|
||||
floppy_image_format_t *fif_list;
|
||||
std::vector<fs_info> m_create_fs, m_io_fs;
|
||||
std::vector<std::unique_ptr<filesystem_manager_t>> m_fs_managers;
|
||||
std::vector<const filesystem_manager_t *> m_fs_managers;
|
||||
emu_timer *index_timer;
|
||||
|
||||
/* Physical characteristics, filled by setup_characteristics */
|
||||
|
@ -18,7 +18,7 @@ struct mame_formats_enumerator {
|
||||
virtual void category(const char *name) = 0;
|
||||
virtual void add(const cassette_image::Format *const *formats) = 0;
|
||||
virtual void add(floppy_format_type format) = 0;
|
||||
virtual void add(filesystem_manager_type fs) = 0;
|
||||
virtual void add(const filesystem_manager_t &fs) = 0;
|
||||
};
|
||||
|
||||
void mame_formats_full_list(mame_formats_enumerator &en);
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "fs_oric_jasmin.h"
|
||||
#include "oric_dsk.h"
|
||||
|
||||
const fs_oric_jasmin FS_ORIC_JASMIN;
|
||||
|
||||
// Floppy only, format is 41 tracks, 1/2 heads, 17 sectors.
|
||||
// Filesystem has no subdirectories.
|
||||
//
|
||||
@ -39,12 +41,22 @@
|
||||
// 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
|
||||
|
||||
const char *fs_oric_jasmin::name() const
|
||||
{
|
||||
return "oric_jasmin";
|
||||
}
|
||||
|
||||
const char *fs_oric_jasmin::description() const
|
||||
{
|
||||
return "Oric Jasmin";
|
||||
}
|
||||
|
||||
void fs_oric_jasmin::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &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");
|
||||
fe.add(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");
|
||||
fe.add(FLOPPY_ORIC_JASMIN_FORMAT, 178432, "oric_jasmin_ss", "Oric Jasmin single-sided");
|
||||
}
|
||||
|
||||
std::unique_ptr<filesystem_t> fs_oric_jasmin::mount(fsblk_t &blockdev) const
|
||||
@ -609,7 +621,3 @@ u32 fs_oric_jasmin::impl::free_block_count()
|
||||
}
|
||||
return nf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const filesystem_manager_type FS_ORIC_JASMIN = &filesystem_manager_creator<fs_oric_jasmin>;;
|
||||
|
@ -102,6 +102,9 @@ public:
|
||||
|
||||
fs_oric_jasmin() : filesystem_manager_t() {}
|
||||
|
||||
virtual const char *name() const override;
|
||||
virtual const char *description() const override;
|
||||
|
||||
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
|
||||
virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override;
|
||||
|
||||
@ -116,6 +119,6 @@ public:
|
||||
static bool validate_filename(std::string name);
|
||||
};
|
||||
|
||||
extern const filesystem_manager_type FS_ORIC_JASMIN;
|
||||
extern const fs_oric_jasmin FS_ORIC_JASMIN;
|
||||
|
||||
#endif
|
||||
|
@ -7,6 +7,19 @@
|
||||
#include "fs_prodos.h"
|
||||
#include "ap_dsk35.h"
|
||||
|
||||
|
||||
const fs_prodos FS_PRODOS;
|
||||
|
||||
const char *fs_prodos::name() const
|
||||
{
|
||||
return "prodos";
|
||||
}
|
||||
|
||||
const char *fs_prodos::description() const
|
||||
{
|
||||
return "Apple ProDOS";
|
||||
}
|
||||
|
||||
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,
|
||||
@ -45,9 +58,9 @@ const u8 fs_prodos::impl::boot[512] = {
|
||||
void fs_prodos::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const
|
||||
{
|
||||
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");
|
||||
fe.add(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");
|
||||
fe.add(FLOPPY_APPLE_GCR_FORMAT, 409600, "prodos_400k", "Apple ProDOS 400K");
|
||||
}
|
||||
|
||||
std::unique_ptr<filesystem_t> fs_prodos::mount(fsblk_t &blockdev) const
|
||||
@ -222,7 +235,7 @@ fs_meta_data fs_prodos::impl::metadata()
|
||||
filesystem_t::dir_t fs_prodos::impl::root()
|
||||
{
|
||||
if(!m_root)
|
||||
m_root = new dir(*this, 2);
|
||||
m_root = new root_dir(*this, 2);
|
||||
return m_root.strong();
|
||||
}
|
||||
|
||||
@ -232,29 +245,18 @@ void fs_prodos::impl::drop_root_ref()
|
||||
}
|
||||
|
||||
|
||||
void fs_prodos::impl::dir::drop_weak_references()
|
||||
void fs_prodos::impl::root_dir::drop_weak_references()
|
||||
{
|
||||
if(m_base_block == 2)
|
||||
m_fs.drop_root_ref();
|
||||
}
|
||||
|
||||
fs_meta_data fs_prodos::impl::dir::metadata()
|
||||
fs_meta_data fs_prodos::impl::root_dir::metadata()
|
||||
{
|
||||
fs_meta_data res;
|
||||
if(m_base_block == 2)
|
||||
return res;
|
||||
|
||||
auto bdir = m_fs.m_blockdev.get(m_base_block);
|
||||
int len = bdir.r8(0x04) & 0xf;
|
||||
res.set(fs_meta_name::name, bdir.rstr(0x05, len));
|
||||
res.set(fs_meta_name::os_version, bdir.r8(0x20));
|
||||
res.set(fs_meta_name::os_minimum_version, bdir.r8(0x21));
|
||||
res.set(fs_meta_name::creation_date, prodos_to_dt(bdir.r32l(0x1c)));
|
||||
res.set(fs_meta_name::modification_date, prodos_to_dt(bdir.r32l(0x16)));
|
||||
return res;
|
||||
return fs_meta_data();
|
||||
}
|
||||
|
||||
std::vector<fs_dir_entry> fs_prodos::impl::dir::contents()
|
||||
std::vector<fs_dir_entry> fs_prodos::impl::root_dir::contents()
|
||||
{
|
||||
std::vector<fs_dir_entry> res;
|
||||
|
||||
@ -282,7 +284,8 @@ std::vector<fs_dir_entry> fs_prodos::impl::dir::contents()
|
||||
return res;
|
||||
}
|
||||
|
||||
std::pair<fsblk_t::block_t, const u8 *> fs_prodos::impl::dir::get_entry_ro(uint64_t key)
|
||||
|
||||
std::pair<fsblk_t::block_t, const u8 *> fs_prodos::impl::root_dir::get_entry_ro(uint64_t key)
|
||||
{
|
||||
std::pair<fsblk_t::block_t, const u8 *> res;
|
||||
res.first = m_fs.m_blockdev.get(m_base_block);
|
||||
@ -300,7 +303,7 @@ std::pair<fsblk_t::block_t, const u8 *> fs_prodos::impl::dir::get_entry_ro(uint6
|
||||
return res;
|
||||
}
|
||||
|
||||
std::pair<fsblk_t::block_t, u8 *> fs_prodos::impl::dir::get_entry(uint64_t key)
|
||||
std::pair<fsblk_t::block_t, u8 *> fs_prodos::impl::root_dir::get_entry(uint64_t key)
|
||||
{
|
||||
std::pair<fsblk_t::block_t, u8 *> res;
|
||||
res.first = m_fs.m_blockdev.get(m_base_block);
|
||||
@ -318,7 +321,7 @@ std::pair<fsblk_t::block_t, u8 *> fs_prodos::impl::dir::get_entry(uint64_t key)
|
||||
return res;
|
||||
}
|
||||
|
||||
filesystem_t::file_t fs_prodos::impl::dir::file_get(uint64_t key)
|
||||
filesystem_t::file_t fs_prodos::impl::root_dir::file_get(uint64_t key)
|
||||
{
|
||||
auto [blk, entry] = get_entry_ro(key);
|
||||
if(!blk)
|
||||
@ -326,10 +329,10 @@ filesystem_t::file_t fs_prodos::impl::dir::file_get(uint64_t key)
|
||||
u8 type = entry[0] >> 4;
|
||||
if(type == 0 || type == 4 || type > 5)
|
||||
fatalerror("Unhandled file type %x\n", type);
|
||||
return new file(m_fs, entry, key);
|
||||
return new file(m_fs, entry, key, this);
|
||||
}
|
||||
|
||||
filesystem_t::dir_t fs_prodos::impl::dir::dir_get(uint64_t key)
|
||||
filesystem_t::dir_t fs_prodos::impl::root_dir::dir_get(uint64_t key)
|
||||
{
|
||||
auto [blk, entry] = get_entry_ro(key);
|
||||
if(!blk)
|
||||
@ -338,13 +341,21 @@ filesystem_t::dir_t fs_prodos::impl::dir::dir_get(uint64_t key)
|
||||
if(type != 0xd)
|
||||
fatalerror("Unhandled directory type %x\n", type);
|
||||
|
||||
return new dir(m_fs, r16l(entry+0x11), key);
|
||||
return new dir(m_fs, entry, r16l(entry+0x11), key, this);
|
||||
}
|
||||
|
||||
fs_prodos::impl::file::file(impl &fs, const u8 *entry, u16 key) : m_fs(fs), m_key(key)
|
||||
fs_prodos::impl::dir::dir(impl &fs, const u8 *entry, u16 base_block, u16 key, root_dir *parent_dir) : root_dir(fs, base_block), m_parent_dir(parent_dir), m_key(key)
|
||||
{
|
||||
memcpy(m_entry, entry, 39);
|
||||
(void)m_key;
|
||||
(void)m_parent_dir;
|
||||
}
|
||||
|
||||
fs_prodos::impl::file::file(impl &fs, const u8 *entry, u16 key, root_dir *parent_dir) : m_fs(fs), m_parent_dir(parent_dir), m_key(key)
|
||||
{
|
||||
memcpy(m_entry, entry, 39);
|
||||
(void)m_key;
|
||||
(void)m_parent_dir;
|
||||
}
|
||||
|
||||
void fs_prodos::impl::file::drop_weak_references()
|
||||
@ -372,32 +383,51 @@ fs_meta_data fs_prodos::impl::file::metadata()
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<uint16_t> fs_prodos::impl::file::get_file_blocks(uint8_t type, u16 block, u32 length)
|
||||
fs_meta_data fs_prodos::impl::dir::metadata()
|
||||
{
|
||||
u32 nb = (length+1)/512;
|
||||
std::vector<uint16_t> res;
|
||||
fs_meta_data res;
|
||||
u8 type = r8(m_entry);
|
||||
std::string name = rstr(m_entry+1, type & 0xf);
|
||||
res.set(fs_meta_name::name, name);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<u8> fs_prodos::impl::file::any_read_all(uint8_t type, u16 block, u32 length)
|
||||
{
|
||||
std::vector<u8> data((length + 511) & ~511);
|
||||
u32 nb = data.size()/512;
|
||||
if(!nb)
|
||||
return data;
|
||||
|
||||
u8 *dst = data.data();
|
||||
u8 *end = dst + data.size();
|
||||
switch(type) {
|
||||
case 1:
|
||||
if(nb)
|
||||
res.push_back(block);
|
||||
memcpy(dst, m_fs.m_blockdev.get(block).rodata(), 512);
|
||||
dst += 512;
|
||||
break;
|
||||
|
||||
case 2: {
|
||||
auto iblk = m_fs.m_blockdev.get(block);
|
||||
if(nb > 255)
|
||||
nb = 255;
|
||||
for(u32 i=0; i != nb; i++)
|
||||
res.push_back(iblk.r8(i) | (iblk.r8(i | 0x100) << 8));
|
||||
for(u32 i=0; i != 256 && dst != end; i++) {
|
||||
u16 blk = iblk.r8(i) | (iblk.r8(i | 0x100) << 8);
|
||||
memcpy(dst, m_fs.m_blockdev.get(blk).rodata(), 512);
|
||||
dst += 512;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
auto mblk = m_fs.m_blockdev.get(block);
|
||||
for(u32 j=0; j < nb; j += 256) {
|
||||
for(u32 j=0; dst != end; j += 256) {
|
||||
u32 idx = j/256;
|
||||
auto iblk = m_fs.m_blockdev.get(mblk.r8(idx) | (mblk.r8(idx | 0x100) << 8));
|
||||
for(u32 i=0; i != 256 && res.size() != nb; i++)
|
||||
res.push_back(iblk.r8(i) | (iblk.r8(i | 0x100) << 8));
|
||||
for(u32 i=0; i != 256 && dst != end; i++) {
|
||||
u16 blk = iblk.r8(i) | (iblk.r8(i | 0x100) << 8);
|
||||
memcpy(dst, m_fs.m_blockdev.get(blk).rodata(), 512);
|
||||
dst += 512;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -405,86 +435,33 @@ std::vector<uint16_t> fs_prodos::impl::file::get_file_blocks(uint8_t type, u16 b
|
||||
default:
|
||||
fatalerror("fs_prodos::impl::file::get_file_blocks: unknown file type %d\n", type);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::pair<std::vector<uint16_t>, u32> fs_prodos::impl::file::data_blocks()
|
||||
{
|
||||
std::vector<uint16_t> blocks;
|
||||
|
||||
u8 type = r8(m_entry) >> 4;
|
||||
u32 length = 0;
|
||||
if(type >= 1 && type <= 3) {
|
||||
length = r24l(m_entry + 0x15);
|
||||
blocks = get_file_blocks(type, r16l(m_entry+0x11), length);
|
||||
|
||||
} else if(type == 5) {
|
||||
auto kblk = m_fs.m_blockdev.get(r16l(m_entry+0x11));
|
||||
length = kblk.r24l(0x005);
|
||||
blocks = get_file_blocks(kblk.r8(0x000), kblk.r16l(0x001), length);
|
||||
|
||||
} else
|
||||
fatalerror("fs_prodos::impl::file::data_blocks: Unhandled file type %d\n", type);
|
||||
|
||||
return std::make_pair(blocks, length);
|
||||
}
|
||||
|
||||
std::pair<std::vector<uint16_t>, u32> fs_prodos::impl::file::rsrc_blocks()
|
||||
{
|
||||
std::vector<uint16_t> blocks;
|
||||
|
||||
u8 type = r8(m_entry) >> 4;
|
||||
u32 length = 0;
|
||||
|
||||
if(type == 5) {
|
||||
auto kblk = m_fs.m_blockdev.get(r16l(m_entry+0x11));
|
||||
length = kblk.r24l(0x105);
|
||||
blocks = get_file_blocks(kblk.r8(0x100), kblk.r16l(0x101), length);
|
||||
|
||||
} else
|
||||
fatalerror("fs_prodos::impl::file::rsrc_blocks: Unhandled file type %d\n", type);
|
||||
|
||||
return std::make_pair(blocks, length);
|
||||
data.resize(length);
|
||||
return data;
|
||||
}
|
||||
|
||||
std::vector<u8> fs_prodos::impl::file::read_all()
|
||||
{
|
||||
auto [blocks, length] = data_blocks();
|
||||
u8 type = r8(m_entry) >> 4;
|
||||
if(type >= 1 && type <= 3)
|
||||
return any_read_all(type, r16l(m_entry+0x11), r24l(m_entry + 0x15));
|
||||
|
||||
std::vector<u8> data(length);
|
||||
u32 pos = 0;
|
||||
for(u16 block : blocks) {
|
||||
u32 npos = pos + 512;
|
||||
if(npos > length)
|
||||
npos = length;
|
||||
if(npos > pos) {
|
||||
auto dblk = m_fs.m_blockdev.get(block);
|
||||
memcpy(data.data() + pos, dblk.rodata(), npos - pos);
|
||||
} else
|
||||
break;
|
||||
pos = npos;
|
||||
}
|
||||
return data;
|
||||
else if(type == 5) {
|
||||
auto kblk = m_fs.m_blockdev.get(r16l(m_entry+0x11));
|
||||
return any_read_all(kblk.r8(0x000), kblk.r16l(0x001), kblk.r24l(0x005));
|
||||
|
||||
} else
|
||||
fatalerror("fs_prodos::impl::file::read_all: Unhandled file type %d\n", type);
|
||||
}
|
||||
|
||||
std::vector<u8> fs_prodos::impl::file::rsrc_read_all()
|
||||
{
|
||||
auto [blocks, length] = rsrc_blocks();
|
||||
u8 type = r8(m_entry) >> 4;
|
||||
|
||||
std::vector<u8> data(length);
|
||||
u32 pos = 0;
|
||||
for(u16 block : blocks) {
|
||||
u32 npos = pos + 512;
|
||||
if(npos > length)
|
||||
npos = length;
|
||||
if(npos > pos) {
|
||||
auto dblk = m_fs.m_blockdev.get(block);
|
||||
memcpy(data.data() + pos, dblk.rodata(), npos - pos);
|
||||
} else
|
||||
break;
|
||||
pos = npos;
|
||||
}
|
||||
return data;
|
||||
if(type == 5) {
|
||||
auto kblk = m_fs.m_blockdev.get(r16l(m_entry+0x11));
|
||||
return any_read_all(kblk.r8(0x100), kblk.r16l(0x101), kblk.r24l(0x105));
|
||||
|
||||
} else
|
||||
fatalerror("fs_prodos::impl::file::rsrc_blocks: Unhandled file type %d\n", type);
|
||||
}
|
||||
|
||||
const filesystem_manager_type FS_PRODOS = &filesystem_manager_creator<fs_prodos>;;
|
||||
|
@ -14,10 +14,10 @@ class fs_prodos : public filesystem_manager_t {
|
||||
public:
|
||||
class impl : public filesystem_t {
|
||||
public:
|
||||
class dir : public idir_t {
|
||||
class root_dir : public idir_t {
|
||||
public:
|
||||
dir(impl &fs, u16 base_block, u16 key = 0) : m_fs(fs), m_base_block(base_block), m_key(key) { (void)m_key; }
|
||||
virtual ~dir() = default;
|
||||
root_dir(impl &fs, u16 base_block) : m_fs(fs), m_base_block(base_block) { }
|
||||
virtual ~root_dir() = default;
|
||||
|
||||
virtual void drop_weak_references() override;
|
||||
|
||||
@ -26,18 +26,30 @@ public:
|
||||
virtual file_t file_get(uint64_t key) override;
|
||||
virtual dir_t dir_get(uint64_t key) override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
impl &m_fs;
|
||||
u16 m_base_block;
|
||||
u16 m_key;
|
||||
|
||||
std::pair<fsblk_t::block_t, const u8 *> get_entry_ro(uint64_t key);
|
||||
std::pair<fsblk_t::block_t, u8 *> get_entry(uint64_t key);
|
||||
};
|
||||
|
||||
class dir : public root_dir {
|
||||
public:
|
||||
dir(impl &fs, const u8 *entry, u16 base_block, u16 key, root_dir *parent_dir);
|
||||
virtual ~dir() = default;
|
||||
|
||||
virtual fs_meta_data metadata() override;
|
||||
|
||||
protected:
|
||||
root_dir *m_parent_dir;
|
||||
u16 m_key;
|
||||
u8 m_entry[39];
|
||||
};
|
||||
|
||||
class file : public ifile_t {
|
||||
public:
|
||||
file(impl &fs, const u8 *entry, u16 key);
|
||||
file(impl &fs, const u8 *entry, u16 key, root_dir *parent_dir);
|
||||
virtual ~file() = default;
|
||||
|
||||
virtual void drop_weak_references() override;
|
||||
@ -48,12 +60,11 @@ public:
|
||||
|
||||
private:
|
||||
impl &m_fs;
|
||||
root_dir *m_parent_dir;
|
||||
u16 m_key;
|
||||
u8 m_entry[39];
|
||||
|
||||
std::vector<uint16_t> get_file_blocks(uint8_t type, u16 block, u32 length);
|
||||
std::pair<std::vector<uint16_t>, uint32_t> data_blocks();
|
||||
std::pair<std::vector<uint16_t>, uint32_t> rsrc_blocks();
|
||||
std::vector<u8> any_read_all(uint8_t type, u16 block, u32 length);
|
||||
};
|
||||
|
||||
impl(fsblk_t &blockdev);
|
||||
@ -67,6 +78,7 @@ public:
|
||||
void drop_root_ref();
|
||||
|
||||
static util::arbitrary_datetime prodos_to_dt(u32 date);
|
||||
std::vector<fs_dir_entry> contents(u16 block);
|
||||
|
||||
private:
|
||||
static const u8 boot[512];
|
||||
@ -76,6 +88,9 @@ public:
|
||||
|
||||
fs_prodos() : filesystem_manager_t() {}
|
||||
|
||||
virtual const char *name() const override;
|
||||
virtual const char *description() const override;
|
||||
|
||||
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
|
||||
virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override;
|
||||
|
||||
@ -90,6 +105,6 @@ public:
|
||||
virtual std::vector<fs_meta_description> directory_meta_description() const override;
|
||||
};
|
||||
|
||||
extern const filesystem_manager_type FS_PRODOS;
|
||||
extern const fs_prodos FS_PRODOS;
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,18 @@
|
||||
#include "emu.h"
|
||||
#include "fs_unformatted.h"
|
||||
|
||||
const fs_unformatted FS_UNFORMATTED;
|
||||
|
||||
const char *fs_unformatted::name() const
|
||||
{
|
||||
return "unformatted";
|
||||
}
|
||||
|
||||
const char *fs_unformatted::description() const
|
||||
{
|
||||
return "Unformatted floppy image";
|
||||
}
|
||||
|
||||
void fs_unformatted::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const
|
||||
{
|
||||
bool all = form_factor == floppy_image::FF_UNKNOWN;
|
||||
@ -120,5 +132,3 @@ bool fs_unformatted::has_rsrc() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const filesystem_manager_type FS_UNFORMATTED = &filesystem_manager_creator<fs_unformatted>;
|
||||
|
@ -38,6 +38,9 @@ public:
|
||||
|
||||
fs_unformatted() : filesystem_manager_t() {}
|
||||
|
||||
virtual const char *name() const override;
|
||||
virtual const char *description() const override;
|
||||
|
||||
static void format(u32 key, floppy_image *image);
|
||||
|
||||
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
|
||||
@ -49,6 +52,6 @@ public:
|
||||
virtual bool has_rsrc() const override;
|
||||
};
|
||||
|
||||
extern const filesystem_manager_type FS_UNFORMATTED;
|
||||
extern const fs_unformatted FS_UNFORMATTED;
|
||||
|
||||
#endif
|
||||
|
@ -391,7 +391,7 @@ public:
|
||||
struct floppy_enumerator {
|
||||
virtual ~floppy_enumerator() = default;
|
||||
|
||||
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(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;
|
||||
};
|
||||
|
||||
@ -410,6 +410,9 @@ public:
|
||||
|
||||
virtual ~filesystem_manager_t() = default;
|
||||
|
||||
virtual const char *name() const = 0;
|
||||
virtual const char *description() const = 0;
|
||||
|
||||
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const;
|
||||
virtual void enumerate_h(hd_enumerator &he) const;
|
||||
virtual void enumerate_c(cdrom_enumerator &ce) const;
|
||||
@ -436,14 +439,4 @@ protected:
|
||||
static bool has_variant(const std::vector<uint32_t> &variants, uint32_t variant);
|
||||
};
|
||||
|
||||
|
||||
typedef filesystem_manager_t *(*filesystem_manager_type)();
|
||||
|
||||
// this template function creates a stub which constructs a filesystem manager
|
||||
template<class _FormatClass>
|
||||
filesystem_manager_t *filesystem_manager_creator()
|
||||
{
|
||||
return new _FormatClass();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
481
src/tools/image_handler.cpp
Normal file
481
src/tools/image_handler.cpp
Normal file
@ -0,0 +1,481 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// Image generic handler class and helpers
|
||||
|
||||
#include "image_handler.h"
|
||||
#include "formats/all.h"
|
||||
#include "formats/fsblk_vec.h"
|
||||
#include "formats/fs_unformatted.h"
|
||||
|
||||
// Fatalerror implementation
|
||||
|
||||
emu_fatalerror::emu_fatalerror(util::format_argument_pack<std::ostream> const &args)
|
||||
: emu_fatalerror(0, args)
|
||||
{
|
||||
}
|
||||
|
||||
emu_fatalerror::emu_fatalerror(int _exitcode, util::format_argument_pack<std::ostream> const &args)
|
||||
: m_text(util::string_format(args))
|
||||
, m_code(_exitcode)
|
||||
{
|
||||
}
|
||||
|
||||
// io_generic from vector<u8>
|
||||
|
||||
static void ram_closeproc(void *file)
|
||||
{
|
||||
auto f = (iofile_ram *)file;
|
||||
delete f;
|
||||
}
|
||||
|
||||
static int ram_seekproc(void *file, int64_t offset, int whence)
|
||||
{
|
||||
auto f = (iofile_ram *)file;
|
||||
switch(whence) {
|
||||
case SEEK_SET: f->pos = offset; break;
|
||||
case SEEK_CUR: f->pos += offset; break;
|
||||
case SEEK_END: f->pos = f->data->size() + offset; break;
|
||||
}
|
||||
|
||||
if(whence == SEEK_CUR)
|
||||
f->pos = std::max<int64_t>(f->pos, 0);
|
||||
else
|
||||
f->pos = std::clamp<int64_t>(f->pos, 0, f->data->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t ram_readproc(void *file, void *buffer, size_t length)
|
||||
{
|
||||
auto f = (iofile_ram *)file;
|
||||
size_t l = std::min<std::common_type_t<size_t, int64_t> >(length, f->data->size() - f->pos);
|
||||
memcpy(buffer, f->data->data() + f->pos, l);
|
||||
return l;
|
||||
}
|
||||
|
||||
static size_t ram_writeproc(void *file, const void *buffer, size_t length)
|
||||
{
|
||||
auto f = (iofile_ram *)file;
|
||||
size_t l = std::max<std::common_type_t<size_t, int64_t> >(f->pos + length, f->data->size());
|
||||
f->data->resize(l);
|
||||
memcpy(f->data->data() + f->pos, buffer, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
static uint64_t ram_filesizeproc(void *file)
|
||||
{
|
||||
auto f = (iofile_ram *)file;
|
||||
return f->data->size();
|
||||
}
|
||||
|
||||
|
||||
static const io_procs iop_ram = {
|
||||
ram_closeproc,
|
||||
ram_seekproc,
|
||||
ram_readproc,
|
||||
ram_writeproc,
|
||||
ram_filesizeproc
|
||||
};
|
||||
|
||||
io_generic *ram_open(std::vector<u8> &data)
|
||||
{
|
||||
iofile_ram *f = new iofile_ram;
|
||||
f->data = &data;
|
||||
f->pos = 0;
|
||||
return new io_generic({ &iop_ram, f });
|
||||
}
|
||||
|
||||
|
||||
// Format enumeration
|
||||
|
||||
namespace {
|
||||
struct enumerator : public mame_formats_enumerator {
|
||||
formats_table *m_table;
|
||||
std::string m_category;
|
||||
|
||||
enumerator(formats_table *table) : mame_formats_enumerator(), m_table(table), m_category("None") {}
|
||||
|
||||
virtual ~enumerator() = default;
|
||||
virtual void add(const cassette_image::Format *const *formats) {}
|
||||
|
||||
virtual void category(const char *name) {
|
||||
m_category = name;
|
||||
}
|
||||
|
||||
virtual void add(floppy_format_type format) {
|
||||
m_table->floppy_format_infos.emplace_back(std::make_unique<floppy_format_info>(format(), m_category));
|
||||
}
|
||||
|
||||
virtual void add(const filesystem_manager_t &fs) {
|
||||
m_table->filesystem_formats.emplace_back(std::make_unique<filesystem_format>(&fs, m_category));
|
||||
}
|
||||
};
|
||||
|
||||
struct fs_enum : public filesystem_manager_t::floppy_enumerator {
|
||||
filesystem_format *m_format;
|
||||
|
||||
fs_enum(filesystem_format *format) : m_format(format) {}
|
||||
|
||||
virtual void add(floppy_format_type type, u32 image_size, const char *name, const char *description) override {
|
||||
m_format->m_floppy = true;
|
||||
m_format->m_floppy_create.emplace_back(std::make_unique<floppy_create_info>(m_format->m_manager, type, image_size, name, description));
|
||||
}
|
||||
|
||||
virtual void add_raw(const char *name, u32 key, const char *description) override {
|
||||
m_format->m_floppy_raw = true;
|
||||
m_format->m_floppy_create.emplace_back(std::make_unique<floppy_create_info>(name, key, description));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void formats_table::init()
|
||||
{
|
||||
std::vector<uint32_t> variants;
|
||||
|
||||
enumerator en(this);
|
||||
mame_formats_full_list(en);
|
||||
|
||||
for(auto &f : filesystem_formats) {
|
||||
fs_enum fen(f.get());
|
||||
f->m_manager->enumerate_f(fen, floppy_image::FF_UNKNOWN, variants);
|
||||
}
|
||||
|
||||
for(auto &f : floppy_format_infos) {
|
||||
auto *ff = f.get();
|
||||
std::string key = ff->m_format->name();
|
||||
auto i = floppy_format_info_by_key.find(key);
|
||||
if(i != floppy_format_info_by_key.end()) {
|
||||
fprintf(stderr, "Collision on floppy format name %s between \"%s\" and \"%s\".\n",
|
||||
ff->m_format->name(),
|
||||
ff->m_format->description(),
|
||||
i->second->m_format->description());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
floppy_format_info_by_key[key] = ff;
|
||||
floppy_format_info_by_category[ff->m_category].push_back(ff);
|
||||
}
|
||||
|
||||
for(auto &f : filesystem_formats) {
|
||||
auto *ff = f.get();
|
||||
std::string key = ff->m_manager->name();
|
||||
auto i = filesystem_format_by_key.find(key);
|
||||
if(i != filesystem_format_by_key.end()) {
|
||||
fprintf(stderr, "Collision on filesystem name %s between \"%s\" and \"%s\".\n",
|
||||
ff->m_manager->name(),
|
||||
ff->m_manager->description(),
|
||||
i->second->m_manager->description());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
filesystem_format_by_key[key] = ff;
|
||||
filesystem_format_by_category[ff->m_category].push_back(ff);
|
||||
|
||||
for(auto &f2 : ff->m_floppy_create) {
|
||||
auto *ff2 = f2.get();
|
||||
key = ff2->m_name;
|
||||
auto i = floppy_create_info_by_key.find(key);
|
||||
if(i != floppy_create_info_by_key.end()) {
|
||||
fprintf(stderr, "Collision on floppy create name %s between \"%s\" and \"%s\".\n",
|
||||
ff2->m_name,
|
||||
ff2->m_description,
|
||||
i->second->m_description);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
floppy_create_info_by_key[key] = ff2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const floppy_format_info *formats_table::find_floppy_format_info_by_key(const std::string &key) const
|
||||
{
|
||||
auto i = floppy_format_info_by_key.find(key);
|
||||
return i == floppy_format_info_by_key.end() ? nullptr : i->second;
|
||||
}
|
||||
|
||||
const filesystem_format *formats_table::find_filesystem_format_by_key(const std::string &key) const
|
||||
{
|
||||
auto i = filesystem_format_by_key.find(key);
|
||||
return i == filesystem_format_by_key.end() ? nullptr : i->second;
|
||||
}
|
||||
|
||||
const floppy_create_info *formats_table::find_floppy_create_info_by_key(const std::string &key) const
|
||||
{
|
||||
auto i = floppy_create_info_by_key.find(key);
|
||||
return i == floppy_create_info_by_key.end() ? nullptr : i->second;
|
||||
}
|
||||
|
||||
|
||||
// Image handling
|
||||
|
||||
std::vector<u8> image_handler::fload(std::string path)
|
||||
{
|
||||
char msg[4096];
|
||||
sprintf(msg, "Error opening %s for reading", path.c_str());
|
||||
auto fi = fopen(path.c_str(), "rb");
|
||||
if(!fi) {
|
||||
perror(msg);
|
||||
exit(1);
|
||||
}
|
||||
fseek(fi, 0, SEEK_END);
|
||||
long size = ftell(fi);
|
||||
std::vector<u8> filedata(size);
|
||||
fseek(fi, 0, SEEK_SET);
|
||||
fread(filedata.data(), filedata.size(), 1, fi);
|
||||
fclose(fi);
|
||||
|
||||
return filedata;
|
||||
}
|
||||
|
||||
std::vector<u8> image_handler::fload_rsrc(std::string path)
|
||||
{
|
||||
auto filedata = fload(path);
|
||||
const u8 *head = filedata.data();
|
||||
|
||||
if(filesystem_t::r32b(head+0x00) == 0x00051607 &&
|
||||
filesystem_t::r32b(head+0x04) == 0x00020000) {
|
||||
u16 nent = filesystem_t::r16b(head+0x18);
|
||||
for(u16 i=0; i != nent; i++) {
|
||||
const u8 *e = head + 12*i;
|
||||
if(filesystem_t::r32b(e+0) == 2) {
|
||||
u32 start = filesystem_t::r32b(e+4);
|
||||
u32 len = filesystem_t::r32b(e+8);
|
||||
filedata.erase(filedata.begin(), filedata.begin() + start);
|
||||
filedata.erase(filedata.begin() + len, filedata.end());
|
||||
return filedata;
|
||||
}
|
||||
}
|
||||
}
|
||||
filedata.clear();
|
||||
return filedata;
|
||||
}
|
||||
|
||||
void image_handler::fsave(std::string path, const std::vector<u8> &data)
|
||||
{
|
||||
char msg[4096];
|
||||
sprintf(msg, "Error opening %s for writing", path.c_str());
|
||||
auto fo = fopen(path.c_str(), "wb");
|
||||
if(!fo) {
|
||||
perror(msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fwrite(data.data(), data.size(), 1, fo);
|
||||
fclose(fo);
|
||||
}
|
||||
|
||||
void image_handler::fsave_rsrc(std::string path, const std::vector<u8> &data)
|
||||
{
|
||||
u8 head[0x2a];
|
||||
|
||||
filesystem_t::w32b(head+0x00, 0x00051607); // Magic
|
||||
filesystem_t::w32b(head+0x04, 0x00020000); // Version
|
||||
filesystem_t::fill(head+0x08, 0, 16); // Filler
|
||||
filesystem_t::w16b(head+0x18, 1); // Number of entries
|
||||
filesystem_t::w32b(head+0x1a, 2); // Resource fork
|
||||
filesystem_t::w32b(head+0x22, 0x2a); // Offset in the file
|
||||
filesystem_t::w32b(head+0x26, data.size()); // Length
|
||||
|
||||
char msg[4096];
|
||||
sprintf(msg, "Error opening %s for writing", path.c_str());
|
||||
auto fo = fopen(path.c_str(), "wb");
|
||||
if(!fo) {
|
||||
perror(msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fwrite(head, sizeof(head), 1, fo);
|
||||
fwrite(data.data(), data.size(), 1, fo);
|
||||
fclose(fo);
|
||||
}
|
||||
|
||||
image_handler::image_handler() : m_floppy_image(84, 2, floppy_image::FF_UNKNOWN)
|
||||
{
|
||||
}
|
||||
|
||||
void image_handler::set_on_disk_path(std::string path)
|
||||
{
|
||||
m_on_disk_path = path;
|
||||
}
|
||||
|
||||
std::vector<std::pair<u8, const floppy_format_info *>> image_handler::identify(const formats_table &formats)
|
||||
{
|
||||
std::vector<std::pair<u8, const floppy_format_info *>> res;
|
||||
std::vector<uint32_t> variants;
|
||||
|
||||
std::string msg = util::string_format("Error opening %s for reading", m_on_disk_path);
|
||||
FILE *f = fopen(m_on_disk_path.c_str(), "rb");
|
||||
if (!f) {
|
||||
perror(msg.c_str());
|
||||
return res;
|
||||
}
|
||||
|
||||
io_generic io;
|
||||
io.file = f;
|
||||
io.procs = &stdio_ioprocs_noclose;
|
||||
io.filler = 0xff;
|
||||
|
||||
for(const auto &e : formats.floppy_format_info_by_key) {
|
||||
u8 score = e.second->m_format->identify(&io, floppy_image::FF_UNKNOWN, variants);
|
||||
if(score)
|
||||
res.emplace_back(std::make_pair(score, e.second));
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool image_handler::floppy_load(const floppy_format_info *format)
|
||||
{
|
||||
std::vector<uint32_t> variants;
|
||||
std::string msg = util::string_format("Error opening %s for reading", m_on_disk_path);
|
||||
FILE *f = fopen(m_on_disk_path.c_str(), "rb");
|
||||
if (!f) {
|
||||
perror(msg.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
io_generic io;
|
||||
io.file = f;
|
||||
io.procs = &stdio_ioprocs_noclose;
|
||||
io.filler = 0xff;
|
||||
|
||||
return !format->m_format->load(&io, floppy_image::FF_UNKNOWN, variants, &m_floppy_image);
|
||||
}
|
||||
|
||||
bool image_handler::floppy_save(const floppy_format_info *format)
|
||||
{
|
||||
std::vector<uint32_t> variants;
|
||||
std::string msg = util::string_format("Error opening %s for writing", m_on_disk_path);
|
||||
FILE *f = fopen(m_on_disk_path.c_str(), "wb");
|
||||
if (!f) {
|
||||
perror(msg.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
io_generic io;
|
||||
io.file = f;
|
||||
io.procs = &stdio_ioprocs_noclose;
|
||||
io.filler = 0xff;
|
||||
|
||||
return !format->m_format->save(&io, variants, &m_floppy_image);
|
||||
}
|
||||
|
||||
void image_handler::floppy_create(const floppy_create_info *format, fs_meta_data meta)
|
||||
{
|
||||
if(format->m_type) {
|
||||
std::vector<uint32_t> variants;
|
||||
std::vector<u8> img(format->m_image_size);
|
||||
fsblk_vec_t blockdev(img);
|
||||
auto fs = format->m_manager->mount(blockdev);
|
||||
fs->format(meta);
|
||||
|
||||
auto iog = ram_open(img);
|
||||
auto source_format = format->m_type();
|
||||
source_format->load(iog, floppy_image::FF_UNKNOWN, variants, &m_floppy_image);
|
||||
delete source_format;
|
||||
delete iog;
|
||||
|
||||
} else
|
||||
fs_unformatted::format(format->m_key, &m_floppy_image);
|
||||
}
|
||||
|
||||
bool image_handler::floppy_mount_fs(const filesystem_format *format)
|
||||
{
|
||||
m_floppy_fs_converter = nullptr;
|
||||
for(const auto &ci : format->m_floppy_create) {
|
||||
if(ci->m_type != m_floppy_fs_converter) {
|
||||
std::vector<uint32_t> variants;
|
||||
m_floppy_fs_converter = ci->m_type;
|
||||
m_sector_image.clear();
|
||||
auto iog = ram_open(m_sector_image);
|
||||
auto load_format = m_floppy_fs_converter();
|
||||
load_format->save(iog, variants, &m_floppy_image);
|
||||
delete load_format;
|
||||
delete iog;
|
||||
}
|
||||
|
||||
if(ci->m_image_size == m_sector_image.size())
|
||||
goto success;
|
||||
}
|
||||
m_floppy_fs_converter = nullptr;
|
||||
m_sector_image.clear();
|
||||
return true;
|
||||
|
||||
success:
|
||||
m_fsblk.reset(new fsblk_vec_t(m_sector_image));
|
||||
m_fsm = format->m_manager;
|
||||
m_fs = m_fsm->mount(*m_fsblk);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool image_handler::hd_mount_fs(const filesystem_format *format)
|
||||
{
|
||||
// Should use the chd mechanisms, one thing at a time...
|
||||
|
||||
m_sector_image = fload(m_on_disk_path);
|
||||
m_fsblk.reset(new fsblk_vec_t(m_sector_image));
|
||||
m_fsm = format->m_manager;
|
||||
m_fs = m_fsm->mount(*m_fsblk);
|
||||
return false;
|
||||
}
|
||||
|
||||
void image_handler::fs_to_floppy()
|
||||
{
|
||||
std::vector<uint32_t> variants;
|
||||
auto iog = ram_open(m_sector_image);
|
||||
auto format = m_floppy_fs_converter();
|
||||
format->load(iog, floppy_image::FF_UNKNOWN, variants, &m_floppy_image);
|
||||
delete format;
|
||||
delete iog;
|
||||
}
|
||||
|
||||
std::vector<std::string> image_handler::path_split(std::string path) const
|
||||
{
|
||||
std::string opath = path;
|
||||
std::vector<std::string> rpath;
|
||||
if(m_fsm->has_subdirectories()) {
|
||||
std::string element;
|
||||
char sep = m_fsm->directory_separator();
|
||||
for(char c : opath) {
|
||||
if(c == sep) {
|
||||
if(!element.empty()) {
|
||||
rpath.push_back(element);
|
||||
element.clear();
|
||||
}
|
||||
} else
|
||||
element += c;
|
||||
}
|
||||
if(!element.empty())
|
||||
rpath.push_back(element);
|
||||
|
||||
} else
|
||||
rpath.push_back(opath);
|
||||
|
||||
return rpath;
|
||||
}
|
||||
|
||||
bool image_handler::fexists(std::string path)
|
||||
{
|
||||
auto f = fopen(path.c_str(), "rb");
|
||||
if(f != nullptr) {
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::string image_handler::path_make_rsrc(std::string path)
|
||||
{
|
||||
auto p = path.end();
|
||||
while(p != path.begin() && p[-1] != '/')
|
||||
p--;
|
||||
std::string rpath(path.begin(), p);
|
||||
rpath += "._";
|
||||
rpath += std::string(p, path.end());
|
||||
return rpath;
|
||||
}
|
||||
|
121
src/tools/image_handler.h
Normal file
121
src/tools/image_handler.h
Normal file
@ -0,0 +1,121 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// Image generic handler class and helpers
|
||||
|
||||
#ifndef TOOLS_IMAGE_HANDLER_H
|
||||
#define TOOLS_IMAGE_HANDLER_H
|
||||
|
||||
#include "../emu/emucore.h"
|
||||
#include "formats/fsmgr.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
using u8 = uint8_t;
|
||||
using u16 = uint16_t;
|
||||
using u32 = uint32_t;
|
||||
|
||||
struct iofile_ram {
|
||||
std::vector<u8> *data;
|
||||
int64_t pos;
|
||||
};
|
||||
|
||||
io_generic *ram_open(std::vector<u8> &data);
|
||||
|
||||
struct floppy_format_info {
|
||||
floppy_image_format_t *m_format;
|
||||
std::string m_category;
|
||||
|
||||
floppy_format_info(floppy_image_format_t *format, std::string category) : m_format(format), m_category(category) {}
|
||||
};
|
||||
|
||||
struct floppy_create_info {
|
||||
const filesystem_manager_t *m_manager;
|
||||
|
||||
floppy_format_type m_type;
|
||||
u32 m_image_size;
|
||||
u32 m_key;
|
||||
const char *m_name;
|
||||
const char *m_description;
|
||||
|
||||
floppy_create_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_key(0), m_name(name), m_description(description)
|
||||
{ }
|
||||
|
||||
floppy_create_info(const char *name, u32 key, const char *description) :
|
||||
m_manager(nullptr), m_type(nullptr), m_image_size(0), m_key(key), m_name(name), m_description(description)
|
||||
{ }
|
||||
};
|
||||
|
||||
struct filesystem_format {
|
||||
const filesystem_manager_t *m_manager;
|
||||
std::vector<std::unique_ptr<floppy_create_info>> m_floppy_create;
|
||||
std::string m_category;
|
||||
bool m_floppy, m_floppy_raw, m_hd, m_cd;
|
||||
|
||||
filesystem_format(const filesystem_manager_t *manager, std::string category) : m_manager(manager), m_category(category), m_floppy(false), m_floppy_raw(false), m_hd(false), m_cd(false) {}
|
||||
};
|
||||
|
||||
struct formats_table {
|
||||
std::vector<std::unique_ptr<floppy_format_info>> floppy_format_infos;
|
||||
std::vector<std::unique_ptr<filesystem_format>> filesystem_formats;
|
||||
|
||||
std::map<std::string, const floppy_format_info *> floppy_format_info_by_key;
|
||||
std::map<std::string, const filesystem_format *> filesystem_format_by_key;
|
||||
std::map<std::string, const floppy_create_info *> floppy_create_info_by_key;
|
||||
|
||||
std::map<std::string, std::vector<const floppy_format_info *>> floppy_format_info_by_category;
|
||||
std::map<std::string, std::vector<const filesystem_format *>> filesystem_format_by_category;
|
||||
|
||||
void init();
|
||||
|
||||
const floppy_format_info *find_floppy_format_info_by_key(const std::string &key) const;
|
||||
const filesystem_format *find_filesystem_format_by_key(const std::string &key) const;
|
||||
const floppy_create_info *find_floppy_create_info_by_key(const std::string &key) const;
|
||||
};
|
||||
|
||||
class image_handler {
|
||||
public:
|
||||
image_handler();
|
||||
|
||||
void set_on_disk_path(std::string path);
|
||||
const std::string &get_on_disk_path() const { return m_on_disk_path; }
|
||||
|
||||
std::vector<std::pair<u8, const floppy_format_info *>> identify(const formats_table &formats);
|
||||
|
||||
bool floppy_load(const floppy_format_info *format);
|
||||
bool floppy_save(const floppy_format_info *format);
|
||||
|
||||
void floppy_create(const floppy_create_info *format, fs_meta_data meta);
|
||||
bool floppy_mount_fs(const filesystem_format *format);
|
||||
bool hd_mount_fs(const filesystem_format *format);
|
||||
void fs_to_floppy();
|
||||
|
||||
std::pair<const filesystem_manager_t *, filesystem_t *> get_fs() const { return std::make_pair(m_fsm, m_fs.get()); }
|
||||
|
||||
std::vector<std::string> path_split(std::string path) const;
|
||||
|
||||
static std::vector<u8> fload(std::string path);
|
||||
static std::vector<u8> fload_rsrc(std::string path);
|
||||
static void fsave(std::string path, const std::vector<u8> &data);
|
||||
static void fsave_rsrc(std::string path, const std::vector<u8> &data);
|
||||
static bool fexists(std::string path);
|
||||
static std::string path_make_rsrc(std::string path);
|
||||
|
||||
private:
|
||||
std::string m_on_disk_path;
|
||||
|
||||
floppy_image m_floppy_image;
|
||||
|
||||
floppy_format_type m_floppy_fs_converter;
|
||||
std::vector<u8> m_sector_image;
|
||||
std::unique_ptr<fsblk_t> m_fsblk;
|
||||
const filesystem_manager_t *m_fsm;
|
||||
std::unique_ptr<filesystem_t> m_fs;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user