mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
Cleanups for the CoCo OS-9 fs module (#9589)
This commit is contained in:
parent
b5c1ac55d1
commit
fc109486e2
@ -17,10 +17,147 @@
|
||||
#include "coco_rawdsk.h"
|
||||
#include "strformat.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DECLARATIONS
|
||||
//**************************************************************************
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace fs;
|
||||
|
||||
// methods
|
||||
std::string pick_os9_string(std::string_view raw_string);
|
||||
std::string to_os9_string(std::string_view s, size_t length);
|
||||
util::arbitrary_datetime from_os9_date(u32 os9_date, u16 os9_time = 0);
|
||||
std::tuple<u32, u16> to_os9_date(const util::arbitrary_datetime &datetime);
|
||||
u32 pick_integer_be(const u8 *data, int length);
|
||||
bool validate_filename(std::string_view name);
|
||||
bool is_ignored_filename(std::string_view name);
|
||||
std::vector<meta_description> entity_meta_description();
|
||||
|
||||
|
||||
// ======================> volume_header
|
||||
|
||||
class volume_header
|
||||
{
|
||||
public:
|
||||
volume_header(fsblk_t::block_t &&block);
|
||||
|
||||
u32 total_sectors() const { return m_block.r24b(0); }
|
||||
u8 track_size_in_sectors() const { return m_block.r8(3); }
|
||||
u16 allocation_bitmap_bytes() const { return m_block.r16b(4); }
|
||||
u16 cluster_size() const { return m_block.r16b(6); }
|
||||
u32 root_dir_lsn() const { return m_block.r24b(8); }
|
||||
u16 owner_id() const { return m_block.r16b(11); }
|
||||
u16 disk_id() const { return m_block.r16b(14); }
|
||||
u8 format_flags() const { return m_block.r8(16); }
|
||||
u16 sectors_per_track() const { return m_block.r16b(17); }
|
||||
u32 bootstrap_lsn() const { return m_block.r24b(21); }
|
||||
u16 bootstrap_size() const { return m_block.r16b(24); }
|
||||
util::arbitrary_datetime creation_date() const { return from_os9_date(m_block.r24b(26), m_block.r16b(29)); }
|
||||
u16 sector_size() const { u16 result = m_block.r16b(104); return result != 0 ? result : 256; }
|
||||
u8 sides() const { return (format_flags() & 0x01) ? 2 : 1; }
|
||||
bool double_density() const { return (format_flags() & 0x02) != 0; }
|
||||
bool double_track() const { return (format_flags() & 0x04) != 0; }
|
||||
bool quad_track_density() const { return (format_flags() & 0x08) != 0; }
|
||||
bool octal_track_density() const { return (format_flags() & 0x10) != 0; }
|
||||
|
||||
std::string name() const;
|
||||
|
||||
private:
|
||||
fsblk_t::block_t m_block;
|
||||
};
|
||||
|
||||
|
||||
// ======================> file_header
|
||||
|
||||
class file_header
|
||||
{
|
||||
public:
|
||||
file_header(fsblk_t::block_t &&block);
|
||||
|
||||
u8 attributes() const { return m_block.r8(0); }
|
||||
u16 owner_id() const { return m_block.r16b(1); }
|
||||
u8 link_count() const { return m_block.r8(8); }
|
||||
u32 file_size() const { return m_block.r32b(9); }
|
||||
util::arbitrary_datetime creation_date() const;
|
||||
bool is_directory() const { return (attributes() & 0x80) != 0; }
|
||||
bool is_non_sharable() const { return (attributes() & 0x40) != 0; }
|
||||
bool is_public_execute() const { return (attributes() & 0x20) != 0; }
|
||||
bool is_public_write() const { return (attributes() & 0x10) != 0; }
|
||||
bool is_public_read() const { return (attributes() & 0x08) != 0; }
|
||||
bool is_user_execute() const { return (attributes() & 0x04) != 0; }
|
||||
bool is_user_write() const { return (attributes() & 0x02) != 0; }
|
||||
bool is_user_read() const { return (attributes() & 0x01) != 0; }
|
||||
|
||||
meta_data metadata() const;
|
||||
int get_sector_map_entry_count() const;
|
||||
void get_sector_map_entry(int entry_number, u32 &start_lsn, u16 &count) const;
|
||||
|
||||
private:
|
||||
fsblk_t::block_t m_block;
|
||||
};
|
||||
|
||||
|
||||
// ======================> impl
|
||||
|
||||
class impl : public filesystem_t {
|
||||
public:
|
||||
class file : public ifile_t {
|
||||
public:
|
||||
file(impl &fs, file_header &&file_header);
|
||||
virtual ~file() = default;
|
||||
|
||||
virtual void drop_weak_references() override;
|
||||
|
||||
virtual meta_data metadata() override;
|
||||
virtual std::vector<u8> read_all() override;
|
||||
|
||||
private:
|
||||
impl &m_fs;
|
||||
file_header m_file_header;
|
||||
};
|
||||
|
||||
class directory : public idir_t {
|
||||
public:
|
||||
directory(impl &i, file_header &&file_header);
|
||||
virtual ~directory() = default;
|
||||
|
||||
virtual void drop_weak_references() override;
|
||||
virtual meta_data metadata() override;
|
||||
virtual std::vector<dir_entry> contents() override;
|
||||
virtual file_t file_get(u64 key) override;
|
||||
virtual dir_t dir_get(u64 key) override;
|
||||
|
||||
private:
|
||||
impl &m_fs;
|
||||
file_header m_file_header;
|
||||
};
|
||||
|
||||
impl(fsblk_t &blockdev, volume_header &&header);
|
||||
virtual ~impl() = default;
|
||||
|
||||
virtual meta_data metadata() override;
|
||||
virtual dir_t root() override;
|
||||
virtual void format(const meta_data &meta) override;
|
||||
|
||||
private:
|
||||
volume_header m_volume_header;
|
||||
dir_t m_root;
|
||||
|
||||
directory *open_directory(u32 lsn);
|
||||
std::vector<u8> read_file_data(const file_header &header) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace fs {
|
||||
|
||||
const coco_os9_image COCO_OS9;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// IMPLEMENTATION
|
||||
@ -30,7 +167,7 @@ const coco_os9_image COCO_OS9;
|
||||
// name
|
||||
//-------------------------------------------------
|
||||
|
||||
const char *coco_os9_image::name() const
|
||||
const char *fs::coco_os9_image::name() const
|
||||
{
|
||||
return "coco_os9";
|
||||
}
|
||||
@ -40,7 +177,7 @@ const char *coco_os9_image::name() const
|
||||
// description
|
||||
//-------------------------------------------------
|
||||
|
||||
const char *coco_os9_image::description() const
|
||||
const char *fs::coco_os9_image::description() const
|
||||
{
|
||||
return "CoCo OS-9";
|
||||
}
|
||||
@ -50,7 +187,7 @@ const char *coco_os9_image::description() const
|
||||
// enumerate_f
|
||||
//-------------------------------------------------
|
||||
|
||||
void coco_os9_image::enumerate_f(floppy_enumerator &fe, u32 form_factor, const std::vector<u32> &variants) const
|
||||
void fs::coco_os9_image::enumerate_f(floppy_enumerator &fe, u32 form_factor, const std::vector<u32> &variants) const
|
||||
{
|
||||
if (has(form_factor, variants, floppy_image::FF_525, floppy_image::SSDD))
|
||||
{
|
||||
@ -64,7 +201,7 @@ void coco_os9_image::enumerate_f(floppy_enumerator &fe, u32 form_factor, const s
|
||||
// can_format
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::can_format() const
|
||||
bool fs::coco_os9_image::can_format() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -74,7 +211,7 @@ bool coco_os9_image::can_format() const
|
||||
// can_read
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::can_read() const
|
||||
bool fs::coco_os9_image::can_read() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -84,7 +221,7 @@ bool coco_os9_image::can_read() const
|
||||
// can_write
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::can_write() const
|
||||
bool fs::coco_os9_image::can_write() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -94,7 +231,7 @@ bool coco_os9_image::can_write() const
|
||||
// has_rsrc
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::has_rsrc() const
|
||||
bool fs::coco_os9_image::has_rsrc() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -104,7 +241,7 @@ bool coco_os9_image::has_rsrc() const
|
||||
// directory_separator
|
||||
//-------------------------------------------------
|
||||
|
||||
char coco_os9_image::directory_separator() const
|
||||
char fs::coco_os9_image::directory_separator() const
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
@ -114,7 +251,7 @@ char coco_os9_image::directory_separator() const
|
||||
// volume_meta_description
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<meta_description> coco_os9_image::volume_meta_description() const
|
||||
std::vector<meta_description> fs::coco_os9_image::volume_meta_description() const
|
||||
{
|
||||
std::vector<meta_description> results;
|
||||
results.emplace_back(meta_description(meta_name::name, "UNTITLED", false, [](const meta_value &m) { return m.as_string().size() <= 32; }, "Volume name, up to 32 characters"));
|
||||
@ -127,7 +264,7 @@ std::vector<meta_description> coco_os9_image::volume_meta_description() const
|
||||
// file_meta_description
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<meta_description> coco_os9_image::file_meta_description() const
|
||||
std::vector<meta_description> fs::coco_os9_image::file_meta_description() const
|
||||
{
|
||||
return entity_meta_description();
|
||||
}
|
||||
@ -137,33 +274,17 @@ std::vector<meta_description> coco_os9_image::file_meta_description() const
|
||||
// directory_meta_description
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<meta_description> coco_os9_image::directory_meta_description() const
|
||||
std::vector<meta_description> fs::coco_os9_image::directory_meta_description() const
|
||||
{
|
||||
return entity_meta_description();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// entity_meta_description
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<meta_description> coco_os9_image::entity_meta_description() const
|
||||
{
|
||||
std::vector<meta_description> results;
|
||||
results.emplace_back(meta_description(meta_name::name, "", false, [](const meta_value &m) { return validate_filename(m.as_string()); }, "File name"));
|
||||
results.emplace_back(meta_description(meta_name::creation_date, util::arbitrary_datetime::now(), false, nullptr, "Creation time"));
|
||||
results.emplace_back(meta_description(meta_name::owner_id, 0, true, nullptr, "Owner ID"));
|
||||
results.emplace_back(meta_description(meta_name::attributes, "", true, nullptr, "File attributes"));
|
||||
results.emplace_back(meta_description(meta_name::length, 0, true, nullptr, "Size of the file in bytes"));
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// mount
|
||||
//-------------------------------------------------
|
||||
|
||||
std::unique_ptr<filesystem_t> coco_os9_image::mount(fsblk_t &blockdev) const
|
||||
std::unique_ptr<filesystem_t> fs::coco_os9_image::mount(fsblk_t &blockdev) const
|
||||
{
|
||||
// read the header block
|
||||
blockdev.set_block_size(256);
|
||||
@ -178,11 +299,29 @@ std::unique_ptr<filesystem_t> coco_os9_image::mount(fsblk_t &blockdev) const
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// entity_meta_description
|
||||
//-------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<meta_description> entity_meta_description()
|
||||
{
|
||||
std::vector<meta_description> results;
|
||||
results.emplace_back(meta_description(meta_name::name, "", false, [](const meta_value &m) { return validate_filename(m.as_string()); }, "File name"));
|
||||
results.emplace_back(meta_description(meta_name::creation_date, util::arbitrary_datetime::now(), false, nullptr, "Creation time"));
|
||||
results.emplace_back(meta_description(meta_name::owner_id, 0, true, nullptr, "Owner ID"));
|
||||
results.emplace_back(meta_description(meta_name::attributes, "", true, nullptr, "File attributes"));
|
||||
results.emplace_back(meta_description(meta_name::length, 0, true, nullptr, "Size of the file in bytes"));
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// pick_os9_string
|
||||
//-------------------------------------------------
|
||||
|
||||
std::string coco_os9_image::pick_os9_string(std::string_view raw_string)
|
||||
std::string pick_os9_string(std::string_view raw_string)
|
||||
{
|
||||
// find the last NUL or high bit character
|
||||
auto iter = std::find_if(raw_string.begin(), raw_string.end(), [](char ch)
|
||||
@ -205,7 +344,7 @@ std::string coco_os9_image::pick_os9_string(std::string_view raw_string)
|
||||
// to_os9_string
|
||||
//-------------------------------------------------
|
||||
|
||||
std::string coco_os9_image::to_os9_string(std::string_view s, size_t length)
|
||||
std::string to_os9_string(std::string_view s, size_t length)
|
||||
{
|
||||
std::string result(length, '\0');
|
||||
for (auto i = 0; i < std::min(length, s.size()); i++)
|
||||
@ -221,7 +360,7 @@ std::string coco_os9_image::to_os9_string(std::string_view s, size_t length)
|
||||
// pick_integer_be
|
||||
//-------------------------------------------------
|
||||
|
||||
u32 coco_os9_image::pick_integer_be(const u8 *data, int length)
|
||||
u32 pick_integer_be(const u8 *data, int length)
|
||||
{
|
||||
u32 result = 0;
|
||||
for (int i = 0; i < length; i++)
|
||||
@ -234,7 +373,7 @@ u32 coco_os9_image::pick_integer_be(const u8 *data, int length)
|
||||
// from_os9_date
|
||||
//-------------------------------------------------
|
||||
|
||||
util::arbitrary_datetime coco_os9_image::from_os9_date(u32 os9_date, u16 os9_time)
|
||||
util::arbitrary_datetime from_os9_date(u32 os9_date, u16 os9_time)
|
||||
{
|
||||
util::arbitrary_datetime dt;
|
||||
memset(&dt, 0, sizeof(dt));
|
||||
@ -251,7 +390,7 @@ util::arbitrary_datetime coco_os9_image::from_os9_date(u32 os9_date, u16 os9_tim
|
||||
// to_os9_date
|
||||
//-------------------------------------------------
|
||||
|
||||
std::tuple<u32, u16> coco_os9_image::to_os9_date(const util::arbitrary_datetime &datetime)
|
||||
std::tuple<u32, u16> to_os9_date(const util::arbitrary_datetime &datetime)
|
||||
{
|
||||
u32 os9_date = ((datetime.year - 1900) & 0xFF) << 16
|
||||
| (datetime.month & 0xFF) << 8
|
||||
@ -266,7 +405,7 @@ std::tuple<u32, u16> coco_os9_image::to_os9_date(const util::arbitrary_datetime
|
||||
// validate_filename
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::validate_filename(std::string_view name)
|
||||
bool validate_filename(std::string_view name)
|
||||
{
|
||||
return !is_ignored_filename(name)
|
||||
&& name.size() <= 29
|
||||
@ -279,7 +418,7 @@ bool coco_os9_image::validate_filename(std::string_view name)
|
||||
// ignored if it is in the file system?
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::is_ignored_filename(std::string_view name)
|
||||
bool is_ignored_filename(std::string_view name)
|
||||
{
|
||||
return name.empty()
|
||||
|| name[0] == '\0'
|
||||
@ -292,7 +431,7 @@ bool coco_os9_image::is_ignored_filename(std::string_view name)
|
||||
// volume_header ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::volume_header::volume_header(fsblk_t::block_t &&block)
|
||||
volume_header::volume_header(fsblk_t::block_t &&block)
|
||||
: m_block(std::move(block))
|
||||
{
|
||||
}
|
||||
@ -302,7 +441,7 @@ coco_os9_image::volume_header::volume_header(fsblk_t::block_t &&block)
|
||||
// volume_header::name
|
||||
//-------------------------------------------------
|
||||
|
||||
std::string coco_os9_image::volume_header::name() const
|
||||
std::string volume_header::name() const
|
||||
{
|
||||
std::string_view raw_name((const char *)&m_block.rodata()[31], 32);
|
||||
return pick_os9_string(raw_name);
|
||||
@ -313,7 +452,7 @@ std::string coco_os9_image::volume_header::name() const
|
||||
// file_header ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::file_header::file_header(fsblk_t::block_t &&block)
|
||||
file_header::file_header(fsblk_t::block_t &&block)
|
||||
: m_block(std::move(block))
|
||||
{
|
||||
}
|
||||
@ -323,7 +462,7 @@ coco_os9_image::file_header::file_header(fsblk_t::block_t &&block)
|
||||
// file_header::creation_date
|
||||
//-------------------------------------------------
|
||||
|
||||
util::arbitrary_datetime coco_os9_image::file_header::creation_date() const
|
||||
util::arbitrary_datetime file_header::creation_date() const
|
||||
{
|
||||
return from_os9_date(m_block.r24b(13));
|
||||
}
|
||||
@ -333,7 +472,7 @@ util::arbitrary_datetime coco_os9_image::file_header::creation_date() const
|
||||
// file_header::metadata
|
||||
//-------------------------------------------------
|
||||
|
||||
meta_data coco_os9_image::file_header::metadata() const
|
||||
meta_data file_header::metadata() const
|
||||
{
|
||||
// format the attributes
|
||||
std::string attributes = util::string_format("%c%c%c%c%c%c%c%c",
|
||||
@ -359,7 +498,7 @@ meta_data coco_os9_image::file_header::metadata() const
|
||||
// file_header::get_sector_map_entry_count
|
||||
//-------------------------------------------------
|
||||
|
||||
int coco_os9_image::file_header::get_sector_map_entry_count() const
|
||||
int file_header::get_sector_map_entry_count() const
|
||||
{
|
||||
return (m_block.size() - 16) / 5;
|
||||
}
|
||||
@ -369,7 +508,7 @@ int coco_os9_image::file_header::get_sector_map_entry_count() const
|
||||
// file_header::get_sector_map_entry
|
||||
//-------------------------------------------------
|
||||
|
||||
void coco_os9_image::file_header::get_sector_map_entry(int entry_number, u32 &start_lsn, u16 &count) const
|
||||
void file_header::get_sector_map_entry(int entry_number, u32 &start_lsn, u16 &count) const
|
||||
{
|
||||
start_lsn = m_block.r24b(16 + (entry_number * 5) + 0);
|
||||
count = m_block.r16b(16 + (entry_number * 5) + 3);
|
||||
@ -380,7 +519,7 @@ void coco_os9_image::file_header::get_sector_map_entry(int entry_number, u32 &st
|
||||
// impl ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::impl::impl(fsblk_t &blockdev, volume_header &&header)
|
||||
impl::impl(fsblk_t &blockdev, volume_header &&header)
|
||||
: filesystem_t(blockdev, 256)
|
||||
, m_volume_header(std::move(header))
|
||||
{
|
||||
@ -391,7 +530,7 @@ coco_os9_image::impl::impl(fsblk_t &blockdev, volume_header &&header)
|
||||
// impl::metadata
|
||||
//-------------------------------------------------
|
||||
|
||||
meta_data coco_os9_image::impl::metadata()
|
||||
meta_data impl::metadata()
|
||||
{
|
||||
meta_data results;
|
||||
results.set(meta_name::name, m_volume_header.name());
|
||||
@ -404,7 +543,7 @@ meta_data coco_os9_image::impl::metadata()
|
||||
// impl::root
|
||||
//-------------------------------------------------
|
||||
|
||||
filesystem_t::dir_t coco_os9_image::impl::root()
|
||||
filesystem_t::dir_t impl::root()
|
||||
{
|
||||
if (!m_root)
|
||||
m_root = open_directory(m_volume_header.root_dir_lsn());
|
||||
@ -412,21 +551,11 @@ filesystem_t::dir_t coco_os9_image::impl::root()
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// impl::drop_root_ref
|
||||
//-------------------------------------------------
|
||||
|
||||
void coco_os9_image::impl::drop_root_ref()
|
||||
{
|
||||
m_root = nullptr;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// impl::format
|
||||
//-------------------------------------------------
|
||||
|
||||
void coco_os9_image::impl::format(const meta_data &meta)
|
||||
void impl::format(const meta_data &meta)
|
||||
{
|
||||
// for some reason, the OS-9 world favored filling with 0xE5
|
||||
m_blockdev.fill(0xE5);
|
||||
@ -536,7 +665,7 @@ void coco_os9_image::impl::format(const meta_data &meta)
|
||||
// impl::open_directory
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::impl::directory *coco_os9_image::impl::open_directory(u32 lsn)
|
||||
impl::directory *impl::open_directory(u32 lsn)
|
||||
{
|
||||
file_header header(m_blockdev.get(lsn));
|
||||
return new directory(*this, std::move(header));
|
||||
@ -547,7 +676,7 @@ coco_os9_image::impl::directory *coco_os9_image::impl::open_directory(u32 lsn)
|
||||
// impl::read_file_data
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<u8> coco_os9_image::impl::read_file_data(const file_header &header) const
|
||||
std::vector<u8> impl::read_file_data(const file_header &header) const
|
||||
{
|
||||
std::vector<u8> data;
|
||||
data.reserve(header.file_size());
|
||||
@ -574,7 +703,7 @@ std::vector<u8> coco_os9_image::impl::read_file_data(const file_header &header)
|
||||
// file ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::impl::file::file(impl &i, file_header &&file_header)
|
||||
impl::file::file(impl &i, file_header &&file_header)
|
||||
: m_fs(i)
|
||||
, m_file_header(std::move(file_header))
|
||||
{
|
||||
@ -585,7 +714,7 @@ coco_os9_image::impl::file::file(impl &i, file_header &&file_header)
|
||||
// file::drop_weak_references
|
||||
//-------------------------------------------------
|
||||
|
||||
void coco_os9_image::impl::file::drop_weak_references()
|
||||
void impl::file::drop_weak_references()
|
||||
{
|
||||
}
|
||||
|
||||
@ -594,7 +723,7 @@ void coco_os9_image::impl::file::drop_weak_references()
|
||||
// file::metadata
|
||||
//-------------------------------------------------
|
||||
|
||||
meta_data coco_os9_image::impl::file::metadata()
|
||||
meta_data impl::file::metadata()
|
||||
{
|
||||
return m_file_header.metadata();
|
||||
}
|
||||
@ -604,7 +733,7 @@ meta_data coco_os9_image::impl::file::metadata()
|
||||
// file::read_all
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<u8> coco_os9_image::impl::file::read_all()
|
||||
std::vector<u8> impl::file::read_all()
|
||||
{
|
||||
return m_fs.read_file_data(m_file_header);
|
||||
}
|
||||
@ -614,7 +743,7 @@ std::vector<u8> coco_os9_image::impl::file::read_all()
|
||||
// directory ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::impl::directory::directory(impl &i, file_header &&file_header)
|
||||
impl::directory::directory(impl &i, file_header &&file_header)
|
||||
: m_fs(i)
|
||||
, m_file_header(std::move(file_header))
|
||||
{
|
||||
@ -625,7 +754,7 @@ coco_os9_image::impl::directory::directory(impl &i, file_header &&file_header)
|
||||
// directory::drop_weak_references
|
||||
//-------------------------------------------------
|
||||
|
||||
void coco_os9_image::impl::directory::drop_weak_references()
|
||||
void impl::directory::drop_weak_references()
|
||||
{
|
||||
}
|
||||
|
||||
@ -634,7 +763,7 @@ void coco_os9_image::impl::directory::drop_weak_references()
|
||||
// directory::metadata
|
||||
//-------------------------------------------------
|
||||
|
||||
meta_data coco_os9_image::impl::directory::metadata()
|
||||
meta_data impl::directory::metadata()
|
||||
{
|
||||
return m_file_header.metadata();
|
||||
}
|
||||
@ -644,7 +773,7 @@ meta_data coco_os9_image::impl::directory::metadata()
|
||||
// directory::contents
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<dir_entry> coco_os9_image::impl::directory::contents()
|
||||
std::vector<dir_entry> impl::directory::contents()
|
||||
{
|
||||
// read the directory data
|
||||
std::vector<u8> directory_data = m_fs.read_file_data(m_file_header);
|
||||
@ -678,7 +807,7 @@ std::vector<dir_entry> coco_os9_image::impl::directory::contents()
|
||||
// directory::file_get
|
||||
//-------------------------------------------------
|
||||
|
||||
filesystem_t::file_t coco_os9_image::impl::directory::file_get(u64 key)
|
||||
filesystem_t::file_t impl::directory::file_get(u64 key)
|
||||
{
|
||||
file_header header(m_fs.m_blockdev.get(u32(key)));
|
||||
return file_t(new file(m_fs, std::move(header)));
|
||||
@ -689,9 +818,9 @@ filesystem_t::file_t coco_os9_image::impl::directory::file_get(u64 key)
|
||||
// directory::dir_get
|
||||
//-------------------------------------------------
|
||||
|
||||
filesystem_t::dir_t coco_os9_image::impl::directory::dir_get(u64 key)
|
||||
filesystem_t::dir_t impl::directory::dir_get(u64 key)
|
||||
{
|
||||
return dir_t(m_fs.open_directory(u32(key)));
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
};
|
||||
|
@ -23,64 +23,7 @@ namespace fs {
|
||||
|
||||
class coco_os9_image : public manager_t {
|
||||
public:
|
||||
class volume_header
|
||||
{
|
||||
public:
|
||||
volume_header(fsblk_t::block_t &&block);
|
||||
|
||||
u32 total_sectors() const { return m_block.r24b(0); }
|
||||
u8 track_size_in_sectors() const { return m_block.r8(3); }
|
||||
u16 allocation_bitmap_bytes() const { return m_block.r16b(4); }
|
||||
u16 cluster_size() const { return m_block.r16b(6); }
|
||||
u32 root_dir_lsn() const { return m_block.r24b(8); }
|
||||
u16 owner_id() const { return m_block.r16b(11); }
|
||||
u16 disk_id() const { return m_block.r16b(14); }
|
||||
u8 format_flags() const { return m_block.r8(16); }
|
||||
u16 sectors_per_track() const { return m_block.r16b(17); }
|
||||
u32 bootstrap_lsn() const { return m_block.r24b(21); }
|
||||
u16 bootstrap_size() const { return m_block.r16b(24); }
|
||||
util::arbitrary_datetime creation_date() const { return from_os9_date(m_block.r24b(26), m_block.r16b(29)); }
|
||||
u16 sector_size() const { u16 result = m_block.r16b(104); return result != 0 ? result : 256; }
|
||||
u8 sides() const { return (format_flags() & 0x01) ? 2 : 1; }
|
||||
bool double_density() const { return (format_flags() & 0x02) != 0; }
|
||||
bool double_track() const { return (format_flags() & 0x04) != 0; }
|
||||
bool quad_track_density() const { return (format_flags() & 0x08) != 0; }
|
||||
bool octal_track_density() const { return (format_flags() & 0x10) != 0; }
|
||||
|
||||
std::string name() const;
|
||||
|
||||
private:
|
||||
fsblk_t::block_t m_block;
|
||||
};
|
||||
|
||||
class file_header
|
||||
{
|
||||
public:
|
||||
file_header(fsblk_t::block_t &&block);
|
||||
|
||||
u8 attributes() const { return m_block.r8(0); }
|
||||
u16 owner_id() const { return m_block.r16b(1); }
|
||||
u8 link_count() const { return m_block.r8(8); }
|
||||
u32 file_size() const { return m_block.r32b(9); }
|
||||
util::arbitrary_datetime creation_date() const;
|
||||
bool is_directory() const { return (attributes() & 0x80) != 0; }
|
||||
bool is_non_sharable() const { return (attributes() & 0x40) != 0; }
|
||||
bool is_public_execute() const { return (attributes() & 0x20) != 0; }
|
||||
bool is_public_write() const { return (attributes() & 0x10) != 0; }
|
||||
bool is_public_read() const { return (attributes() & 0x08) != 0; }
|
||||
bool is_user_execute() const { return (attributes() & 0x04) != 0; }
|
||||
bool is_user_write() const { return (attributes() & 0x02) != 0; }
|
||||
bool is_user_read() const { return (attributes() & 0x01) != 0; }
|
||||
|
||||
meta_data metadata() const;
|
||||
int get_sector_map_entry_count() const;
|
||||
void get_sector_map_entry(int entry_number, u32 &start_lsn, u16 &count) const;
|
||||
|
||||
private:
|
||||
fsblk_t::block_t m_block;
|
||||
};
|
||||
|
||||
coco_os9_image() : manager_t() {}
|
||||
coco_os9_image() = default;
|
||||
|
||||
virtual const char *name() const override;
|
||||
virtual const char *description() const override;
|
||||
@ -97,65 +40,6 @@ public:
|
||||
virtual std::vector<meta_description> volume_meta_description() const override;
|
||||
virtual std::vector<meta_description> file_meta_description() const override;
|
||||
virtual std::vector<meta_description> directory_meta_description() const override;
|
||||
std::vector<meta_description> entity_meta_description() const;
|
||||
|
||||
private:
|
||||
class impl : public filesystem_t {
|
||||
public:
|
||||
class file : public ifile_t {
|
||||
public:
|
||||
file(impl &fs, file_header &&file_header);
|
||||
virtual ~file() = default;
|
||||
|
||||
virtual void drop_weak_references() override;
|
||||
|
||||
virtual meta_data metadata() override;
|
||||
virtual std::vector<u8> read_all() override;
|
||||
|
||||
private:
|
||||
impl & m_fs;
|
||||
file_header m_file_header;
|
||||
};
|
||||
|
||||
class directory : public idir_t {
|
||||
public:
|
||||
directory(impl &i, file_header &&file_header);
|
||||
virtual ~directory() = default;
|
||||
|
||||
virtual void drop_weak_references() override;
|
||||
virtual meta_data metadata() override;
|
||||
virtual std::vector<dir_entry> contents() override;
|
||||
virtual file_t file_get(u64 key) override;
|
||||
virtual dir_t dir_get(u64 key) override;
|
||||
|
||||
private:
|
||||
impl & m_fs;
|
||||
file_header m_file_header;
|
||||
};
|
||||
|
||||
impl(fsblk_t &blockdev, volume_header &&header);
|
||||
virtual ~impl() = default;
|
||||
|
||||
virtual meta_data metadata() override;
|
||||
virtual dir_t root() override;
|
||||
virtual void format(const meta_data &meta) override;
|
||||
|
||||
private:
|
||||
volume_header m_volume_header;
|
||||
dir_t m_root;
|
||||
|
||||
directory *open_directory(u32 lsn);
|
||||
void drop_root_ref();
|
||||
std::vector<u8> read_file_data(const file_header &header) const;
|
||||
};
|
||||
|
||||
static std::string pick_os9_string(std::string_view raw_string);
|
||||
static std::string to_os9_string(std::string_view s, size_t length);
|
||||
static util::arbitrary_datetime from_os9_date(u32 os9_date, u16 os9_time = 0);
|
||||
static std::tuple<u32, u16> to_os9_date(const util::arbitrary_datetime &datetime);
|
||||
static u32 pick_integer_be(const u8 *data, int length);
|
||||
static bool validate_filename(std::string_view name);
|
||||
static bool is_ignored_filename(std::string_view name);
|
||||
};
|
||||
|
||||
extern const coco_os9_image COCO_OS9;
|
||||
|
Loading…
Reference in New Issue
Block a user