mirror of
https://github.com/holub/mame
synced 2025-07-03 17:08:39 +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 "coco_rawdsk.h"
|
||||||
#include "strformat.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 {
|
namespace fs {
|
||||||
|
|
||||||
const coco_os9_image COCO_OS9;
|
const coco_os9_image COCO_OS9;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
// IMPLEMENTATION
|
// IMPLEMENTATION
|
||||||
@ -30,7 +167,7 @@ const coco_os9_image COCO_OS9;
|
|||||||
// name
|
// name
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
const char *coco_os9_image::name() const
|
const char *fs::coco_os9_image::name() const
|
||||||
{
|
{
|
||||||
return "coco_os9";
|
return "coco_os9";
|
||||||
}
|
}
|
||||||
@ -40,7 +177,7 @@ const char *coco_os9_image::name() const
|
|||||||
// description
|
// description
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
const char *coco_os9_image::description() const
|
const char *fs::coco_os9_image::description() const
|
||||||
{
|
{
|
||||||
return "CoCo OS-9";
|
return "CoCo OS-9";
|
||||||
}
|
}
|
||||||
@ -50,7 +187,7 @@ const char *coco_os9_image::description() const
|
|||||||
// enumerate_f
|
// 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))
|
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
|
// can_format
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
bool coco_os9_image::can_format() const
|
bool fs::coco_os9_image::can_format() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -74,7 +211,7 @@ bool coco_os9_image::can_format() const
|
|||||||
// can_read
|
// can_read
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
bool coco_os9_image::can_read() const
|
bool fs::coco_os9_image::can_read() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -84,7 +221,7 @@ bool coco_os9_image::can_read() const
|
|||||||
// can_write
|
// can_write
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
bool coco_os9_image::can_write() const
|
bool fs::coco_os9_image::can_write() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -94,7 +231,7 @@ bool coco_os9_image::can_write() const
|
|||||||
// has_rsrc
|
// has_rsrc
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
bool coco_os9_image::has_rsrc() const
|
bool fs::coco_os9_image::has_rsrc() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -104,7 +241,7 @@ bool coco_os9_image::has_rsrc() const
|
|||||||
// directory_separator
|
// directory_separator
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
char coco_os9_image::directory_separator() const
|
char fs::coco_os9_image::directory_separator() const
|
||||||
{
|
{
|
||||||
return '/';
|
return '/';
|
||||||
}
|
}
|
||||||
@ -114,7 +251,7 @@ char coco_os9_image::directory_separator() const
|
|||||||
// volume_meta_description
|
// 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;
|
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"));
|
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
|
// 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();
|
return entity_meta_description();
|
||||||
}
|
}
|
||||||
@ -137,33 +274,17 @@ std::vector<meta_description> coco_os9_image::file_meta_description() const
|
|||||||
// directory_meta_description
|
// 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();
|
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
|
// 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
|
// read the header block
|
||||||
blockdev.set_block_size(256);
|
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
|
// 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
|
// find the last NUL or high bit character
|
||||||
auto iter = std::find_if(raw_string.begin(), raw_string.end(), [](char ch)
|
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
|
// 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');
|
std::string result(length, '\0');
|
||||||
for (auto i = 0; i < std::min(length, s.size()); i++)
|
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
|
// 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;
|
u32 result = 0;
|
||||||
for (int i = 0; i < length; i++)
|
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
|
// 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;
|
util::arbitrary_datetime dt;
|
||||||
memset(&dt, 0, sizeof(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
|
// 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
|
u32 os9_date = ((datetime.year - 1900) & 0xFF) << 16
|
||||||
| (datetime.month & 0xFF) << 8
|
| (datetime.month & 0xFF) << 8
|
||||||
@ -266,7 +405,7 @@ std::tuple<u32, u16> coco_os9_image::to_os9_date(const util::arbitrary_datetime
|
|||||||
// validate_filename
|
// validate_filename
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
bool coco_os9_image::validate_filename(std::string_view name)
|
bool validate_filename(std::string_view name)
|
||||||
{
|
{
|
||||||
return !is_ignored_filename(name)
|
return !is_ignored_filename(name)
|
||||||
&& name.size() <= 29
|
&& 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?
|
// 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()
|
return name.empty()
|
||||||
|| name[0] == '\0'
|
|| name[0] == '\0'
|
||||||
@ -292,7 +431,7 @@ bool coco_os9_image::is_ignored_filename(std::string_view name)
|
|||||||
// volume_header ctor
|
// 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))
|
: m_block(std::move(block))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -302,7 +441,7 @@ coco_os9_image::volume_header::volume_header(fsblk_t::block_t &&block)
|
|||||||
// volume_header::name
|
// 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);
|
std::string_view raw_name((const char *)&m_block.rodata()[31], 32);
|
||||||
return pick_os9_string(raw_name);
|
return pick_os9_string(raw_name);
|
||||||
@ -313,7 +452,7 @@ std::string coco_os9_image::volume_header::name() const
|
|||||||
// file_header ctor
|
// 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))
|
: 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
|
// 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));
|
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
|
// file_header::metadata
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
meta_data coco_os9_image::file_header::metadata() const
|
meta_data file_header::metadata() const
|
||||||
{
|
{
|
||||||
// format the attributes
|
// format the attributes
|
||||||
std::string attributes = util::string_format("%c%c%c%c%c%c%c%c",
|
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
|
// 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;
|
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
|
// 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);
|
start_lsn = m_block.r24b(16 + (entry_number * 5) + 0);
|
||||||
count = m_block.r16b(16 + (entry_number * 5) + 3);
|
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
|
// 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)
|
: filesystem_t(blockdev, 256)
|
||||||
, m_volume_header(std::move(header))
|
, m_volume_header(std::move(header))
|
||||||
{
|
{
|
||||||
@ -391,7 +530,7 @@ coco_os9_image::impl::impl(fsblk_t &blockdev, volume_header &&header)
|
|||||||
// impl::metadata
|
// impl::metadata
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
meta_data coco_os9_image::impl::metadata()
|
meta_data impl::metadata()
|
||||||
{
|
{
|
||||||
meta_data results;
|
meta_data results;
|
||||||
results.set(meta_name::name, m_volume_header.name());
|
results.set(meta_name::name, m_volume_header.name());
|
||||||
@ -404,7 +543,7 @@ meta_data coco_os9_image::impl::metadata()
|
|||||||
// impl::root
|
// impl::root
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
filesystem_t::dir_t coco_os9_image::impl::root()
|
filesystem_t::dir_t impl::root()
|
||||||
{
|
{
|
||||||
if (!m_root)
|
if (!m_root)
|
||||||
m_root = open_directory(m_volume_header.root_dir_lsn());
|
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
|
// 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
|
// for some reason, the OS-9 world favored filling with 0xE5
|
||||||
m_blockdev.fill(0xE5);
|
m_blockdev.fill(0xE5);
|
||||||
@ -536,7 +665,7 @@ void coco_os9_image::impl::format(const meta_data &meta)
|
|||||||
// impl::open_directory
|
// 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));
|
file_header header(m_blockdev.get(lsn));
|
||||||
return new directory(*this, std::move(header));
|
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
|
// 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;
|
std::vector<u8> data;
|
||||||
data.reserve(header.file_size());
|
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
|
// 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_fs(i)
|
||||||
, m_file_header(std::move(file_header))
|
, 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
|
// 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
|
// file::metadata
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
meta_data coco_os9_image::impl::file::metadata()
|
meta_data impl::file::metadata()
|
||||||
{
|
{
|
||||||
return m_file_header.metadata();
|
return m_file_header.metadata();
|
||||||
}
|
}
|
||||||
@ -604,7 +733,7 @@ meta_data coco_os9_image::impl::file::metadata()
|
|||||||
// file::read_all
|
// 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);
|
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
|
// 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_fs(i)
|
||||||
, m_file_header(std::move(file_header))
|
, 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
|
// 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
|
// directory::metadata
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
meta_data coco_os9_image::impl::directory::metadata()
|
meta_data impl::directory::metadata()
|
||||||
{
|
{
|
||||||
return m_file_header.metadata();
|
return m_file_header.metadata();
|
||||||
}
|
}
|
||||||
@ -644,7 +773,7 @@ meta_data coco_os9_image::impl::directory::metadata()
|
|||||||
// directory::contents
|
// directory::contents
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
std::vector<dir_entry> coco_os9_image::impl::directory::contents()
|
std::vector<dir_entry> impl::directory::contents()
|
||||||
{
|
{
|
||||||
// read the directory data
|
// read the directory data
|
||||||
std::vector<u8> directory_data = m_fs.read_file_data(m_file_header);
|
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
|
// 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)));
|
file_header header(m_fs.m_blockdev.get(u32(key)));
|
||||||
return file_t(new file(m_fs, std::move(header)));
|
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
|
// 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)));
|
return dir_t(m_fs.open_directory(u32(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fs
|
};
|
||||||
|
@ -23,64 +23,7 @@ namespace fs {
|
|||||||
|
|
||||||
class coco_os9_image : public manager_t {
|
class coco_os9_image : public manager_t {
|
||||||
public:
|
public:
|
||||||
class volume_header
|
coco_os9_image() = default;
|
||||||
{
|
|
||||||
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() {}
|
|
||||||
|
|
||||||
virtual const char *name() const override;
|
virtual const char *name() const override;
|
||||||
virtual const char *description() 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> volume_meta_description() const override;
|
||||||
virtual std::vector<meta_description> file_meta_description() const override;
|
virtual std::vector<meta_description> file_meta_description() const override;
|
||||||
virtual std::vector<meta_description> directory_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;
|
extern const coco_os9_image COCO_OS9;
|
||||||
|
Loading…
Reference in New Issue
Block a user