mirror of
https://github.com/holub/mame
synced 2025-04-16 21:44:32 +03:00
Created an initial file system implementation for OS-9 under the CoCo (#9096)
* Created an initial file system implementation for OS-9 under the CoCo * Minor fixes to directory entry handling * Changed to use fsblk_t::r[8|16|24|32]b() - Changed the above functions to be const
This commit is contained in:
parent
3abc1a4805
commit
fd73621285
@ -2124,4 +2124,16 @@ if opt_tool(FORMATS, "FS_COCO_RSDOS") then
|
||||
}
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
--
|
||||
--@src/lib/formats/fs_coco_os9.h,FORMATS["FS_COCO_OS9"] = true
|
||||
--------------------------------------------------
|
||||
|
||||
if opt_tool(FORMATS, "FS_COCO_OS9") then
|
||||
files {
|
||||
MAME_DIR.. "src/lib/formats/fs_coco_os9.cpp",
|
||||
MAME_DIR.. "src/lib/formats/fs_coco_os9.h",
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1185,6 +1185,7 @@ FORMATS["ZX81_P"] = true
|
||||
FORMATS["FS_PRODOS"] = true
|
||||
FORMATS["FS_ORIC_JASMIN"] = true
|
||||
FORMATS["FS_COCO_RSDOS"] = true
|
||||
FORMATS["FS_COCO_OS9"] = true
|
||||
|
||||
--------------------------------------------------
|
||||
-- this is the list of driver libraries that
|
||||
|
@ -364,6 +364,10 @@
|
||||
#include "fs_coco_rsdos.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAS_FORMATS_FS_COCO_OS9
|
||||
#include "fs_coco_os9.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAS_FORMATS_JFD_DSK
|
||||
#include "jfd_dsk.h"
|
||||
#endif
|
||||
@ -1085,6 +1089,9 @@ void mame_formats_full_list(mame_formats_enumerator &en)
|
||||
#ifdef HAS_FORMATS_FS_COCO_RSDOS
|
||||
en.add(fs::COCO_RSDOS); // fs_coco_rsdos.h
|
||||
#endif
|
||||
#ifdef HAS_FORMATS_FS_COCO_OS9
|
||||
en.add(fs::COCO_OS9); // fs_coco_os9.h
|
||||
#endif
|
||||
|
||||
en.category("Kaypro");
|
||||
#ifdef HAS_FORMATS_KAYPRO_DSK
|
||||
|
542
src/lib/formats/fs_coco_os9.cpp
Normal file
542
src/lib/formats/fs_coco_os9.cpp
Normal file
@ -0,0 +1,542 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Nathan Woods
|
||||
/***************************************************************************
|
||||
|
||||
fs_coco_os9.cpp
|
||||
|
||||
Management of CoCo OS-9 floppy images
|
||||
|
||||
OS-9 Level 2 Technical Reference, Chapter 5, Random Block File Manager,
|
||||
page 2
|
||||
|
||||
http://www.colorcomputerarchive.com/coco/Documents/Manuals/Operating Systems/OS-9 Level 2 Manual (Tandy).pdf
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "fs_coco_os9.h"
|
||||
#include "coco_rawdsk.h"
|
||||
#include "strformat.h"
|
||||
|
||||
namespace fs {
|
||||
|
||||
const coco_os9_image COCO_OS9;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// IMPLEMENTATION
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// name
|
||||
//-------------------------------------------------
|
||||
|
||||
const char *coco_os9_image::name() const
|
||||
{
|
||||
return "coco_os9";
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// description
|
||||
//-------------------------------------------------
|
||||
|
||||
const char *coco_os9_image::description() const
|
||||
{
|
||||
return "CoCo OS-9";
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// enumerate_f
|
||||
//-------------------------------------------------
|
||||
|
||||
void 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))
|
||||
{
|
||||
fe.add(FLOPPY_COCO_RAWDSK_FORMAT, 161280, "coco_rawdsk_os9_35", "CoCo Raw Disk OS-9 single-sided 35 tracks");
|
||||
fe.add(FLOPPY_COCO_RAWDSK_FORMAT, 184320, "coco_rawdsk_os9_40", "CoCo Raw Disk OS-9 single-sided 40 tracks");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// can_format
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::can_format() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// can_read
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::can_read() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// can_write
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::can_write() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// has_rsrc
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::has_rsrc() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// directory_separator
|
||||
//-------------------------------------------------
|
||||
|
||||
char coco_os9_image::directory_separator() const
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// volume_meta_description
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<meta_description> coco_os9_image::volume_meta_description() const
|
||||
{
|
||||
std::vector<meta_description> results;
|
||||
results.emplace_back(meta_description(meta_name::name, meta_type::string, "UNTITLED", false, [](const meta_value &m) { return m.as_string().size() <= 32; }, "Volume name, up to 32 characters"));
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// file_meta_description
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<meta_description> coco_os9_image::file_meta_description() const
|
||||
{
|
||||
return entity_meta_description();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// directory_meta_description
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<meta_description> 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, meta_type::string, "", false, [](const meta_value &m) { return validate_filename(m.as_string()); }, "File name"));
|
||||
results.emplace_back(meta_description(meta_name::creation_date, meta_type::date, util::arbitrary_datetime::now(), false, nullptr, "Creation time"));
|
||||
results.emplace_back(meta_description(meta_name::owner_id, meta_type::number, 0, true, nullptr, "Owner ID"));
|
||||
results.emplace_back(meta_description(meta_name::attributes, meta_type::string, 0, true, nullptr, "File attributes"));
|
||||
results.emplace_back(meta_description(meta_name::length, meta_type::number, 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
|
||||
{
|
||||
// read the header block
|
||||
blockdev.set_block_size(256);
|
||||
volume_header header(blockdev.get(0));
|
||||
|
||||
// sanity checks
|
||||
if (header.sectors_per_track() != header.track_size_in_sectors())
|
||||
return { };
|
||||
|
||||
// create the implementation
|
||||
return std::make_unique<impl>(blockdev, std::move(header));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// pick_os9_string
|
||||
//-------------------------------------------------
|
||||
|
||||
std::string coco_os9_image::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)
|
||||
{
|
||||
return ch == '\0' || ch & 0x80;
|
||||
});
|
||||
|
||||
// get the preliminary result
|
||||
std::string result(raw_string.begin(), iter);
|
||||
|
||||
// and add the final character if we have to
|
||||
if (iter < raw_string.end() && *iter & 0x80)
|
||||
result.append(1, *iter & 0x7F);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// pick_integer_be
|
||||
//-------------------------------------------------
|
||||
|
||||
u32 coco_os9_image::pick_integer_be(const u8 *data, int length)
|
||||
{
|
||||
u32 result = 0;
|
||||
for (int i = 0; i < length; i++)
|
||||
result |= ((u32)data[length - i - 1]) << i * 8;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// validate_filename
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::validate_filename(std::string_view name)
|
||||
{
|
||||
return !is_ignored_filename(name)
|
||||
&& name.size() <= 29
|
||||
&& std::find_if(name.begin(), name.end(), [](const char ch) { return ch == '\0' || ch == '/' || ch >= 0x80; }) == name.end();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// is_ignored_filename - should this file name be
|
||||
// ignored if it is in the file system?
|
||||
//-------------------------------------------------
|
||||
|
||||
bool coco_os9_image::is_ignored_filename(std::string_view name)
|
||||
{
|
||||
return name.empty()
|
||||
|| name[0] == '\0'
|
||||
|| name == "."
|
||||
|| name == "..";
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// volume_header ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::volume_header::volume_header(fsblk_t::block_t &&block)
|
||||
: m_block(std::move(block))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// volume_header::name
|
||||
//-------------------------------------------------
|
||||
|
||||
std::string coco_os9_image::volume_header::name() const
|
||||
{
|
||||
std::string_view raw_name((const char *)&m_block.rodata()[31], 32);
|
||||
return pick_os9_string(raw_name);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// file_header ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::file_header::file_header(fsblk_t::block_t &&block)
|
||||
: m_block(std::move(block))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// file_header::creation_date
|
||||
//-------------------------------------------------
|
||||
|
||||
util::arbitrary_datetime coco_os9_image::file_header::creation_date() const
|
||||
{
|
||||
util::arbitrary_datetime dt;
|
||||
memset(&dt, 0, sizeof(dt));
|
||||
dt.year = 1900 + m_block.r8(13);
|
||||
dt.month = m_block.r8(14);
|
||||
dt.day_of_month = m_block.r8(15);
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// file_header::metadata
|
||||
//-------------------------------------------------
|
||||
|
||||
meta_data coco_os9_image::file_header::metadata() const
|
||||
{
|
||||
// format the attributes
|
||||
std::string attributes = util::string_format("%c%c%c%c%c%c%c%c",
|
||||
is_directory() ? 'd' : '-',
|
||||
is_non_sharable() ? 's' : '-',
|
||||
is_public_execute() ? 'x' : '-',
|
||||
is_public_write() ? 'w' : '-',
|
||||
is_public_read() ? 'r' : '-',
|
||||
is_user_execute() ? 'x' : '-',
|
||||
is_user_write() ? 'w' : '-',
|
||||
is_user_read() ? 'r' : '-');
|
||||
|
||||
meta_data result;
|
||||
result.set(meta_name::creation_date, creation_date());
|
||||
result.set(meta_name::owner_id, owner_id());
|
||||
result.set(meta_name::attributes, std::move(attributes));
|
||||
result.set(meta_name::length, file_size());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// file_header::get_sector_map_entry_count
|
||||
//-------------------------------------------------
|
||||
|
||||
int coco_os9_image::file_header::get_sector_map_entry_count() const
|
||||
{
|
||||
return (m_block.size() - 16) / 5;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// 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
|
||||
{
|
||||
start_lsn = m_block.r24b(16 + (entry_number * 5) + 0);
|
||||
count = m_block.r16b(16 + (entry_number * 5) + 3);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// impl ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::impl::impl(fsblk_t &blockdev, volume_header &&header)
|
||||
: filesystem_t(blockdev, 256)
|
||||
, m_volume_header(std::move(header))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// impl::metadata
|
||||
//-------------------------------------------------
|
||||
|
||||
meta_data coco_os9_image::impl::metadata()
|
||||
{
|
||||
meta_data results;
|
||||
results.set(meta_name::name, m_volume_header.name());
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// impl::root
|
||||
//-------------------------------------------------
|
||||
|
||||
filesystem_t::dir_t coco_os9_image::impl::root()
|
||||
{
|
||||
if (!m_root)
|
||||
m_root = open_directory(m_volume_header.root_dir_lsn());
|
||||
return m_root.strong();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// impl::drop_root_ref
|
||||
//-------------------------------------------------
|
||||
|
||||
void coco_os9_image::impl::drop_root_ref()
|
||||
{
|
||||
m_root = nullptr;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// impl::open_directory
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::impl::directory *coco_os9_image::impl::open_directory(u32 lsn)
|
||||
{
|
||||
file_header header(m_blockdev.get(lsn));
|
||||
return new directory(*this, std::move(header));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// impl::read_file_data
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<u8> coco_os9_image::impl::read_file_data(const file_header &header) const
|
||||
{
|
||||
std::vector<u8> data;
|
||||
data.reserve(header.file_size());
|
||||
int entry_count = header.get_sector_map_entry_count();
|
||||
for (int i = 0; i < entry_count; i++)
|
||||
{
|
||||
u32 start_lsn;
|
||||
u16 count;
|
||||
header.get_sector_map_entry(i, start_lsn, count);
|
||||
|
||||
for (u32 lsn = start_lsn; lsn < start_lsn + count; lsn++)
|
||||
{
|
||||
auto block = m_blockdev.get(lsn);
|
||||
size_t block_size = std::min(std::min((u32)m_volume_header.sector_size(), block.size()), header.file_size() - (u32)data.size());
|
||||
for (auto i = 0; i < block_size; i++)
|
||||
data.push_back(block.rodata()[i]);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// file ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::impl::file::file(impl &i, file_header &&file_header)
|
||||
: m_fs(i)
|
||||
, m_file_header(std::move(file_header))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// file::drop_weak_references
|
||||
//-------------------------------------------------
|
||||
|
||||
void coco_os9_image::impl::file::drop_weak_references()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// file::metadata
|
||||
//-------------------------------------------------
|
||||
|
||||
meta_data coco_os9_image::impl::file::metadata()
|
||||
{
|
||||
return m_file_header.metadata();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// file::read_all
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<u8> coco_os9_image::impl::file::read_all()
|
||||
{
|
||||
return m_fs.read_file_data(m_file_header);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// directory ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
coco_os9_image::impl::directory::directory(impl &i, file_header &&file_header)
|
||||
: m_fs(i)
|
||||
, m_file_header(std::move(file_header))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// directory::drop_weak_references
|
||||
//-------------------------------------------------
|
||||
|
||||
void coco_os9_image::impl::directory::drop_weak_references()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// directory::metadata
|
||||
//-------------------------------------------------
|
||||
|
||||
meta_data coco_os9_image::impl::directory::metadata()
|
||||
{
|
||||
return m_file_header.metadata();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// directory::contents
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<dir_entry> coco_os9_image::impl::directory::contents()
|
||||
{
|
||||
// read the directory data
|
||||
std::vector<u8> directory_data = m_fs.read_file_data(m_file_header);
|
||||
|
||||
// and assemble results
|
||||
std::vector<dir_entry> results;
|
||||
int directory_count = directory_data.size() / 32;
|
||||
for (int i = 0; i < directory_count; i++)
|
||||
{
|
||||
// determine the filename
|
||||
std::string_view raw_filename((const char *) &directory_data[i * 32], 29);
|
||||
std::string filename = pick_os9_string(raw_filename);
|
||||
if (is_ignored_filename(filename))
|
||||
continue;
|
||||
|
||||
// determine the entry type
|
||||
u32 lsn = pick_integer_be(&directory_data[i * 32] + 29, 3);
|
||||
file_header file_header(m_fs.m_blockdev.get(lsn));
|
||||
dir_entry_type entry_type = file_header.is_directory()
|
||||
? dir_entry_type::dir
|
||||
: dir_entry_type::file;
|
||||
|
||||
// and return the results
|
||||
results.emplace_back(std::move(filename), entry_type, lsn);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// directory::file_get
|
||||
//-------------------------------------------------
|
||||
|
||||
filesystem_t::file_t coco_os9_image::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)));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// directory::dir_get
|
||||
//-------------------------------------------------
|
||||
|
||||
filesystem_t::dir_t coco_os9_image::impl::directory::dir_get(u64 key)
|
||||
{
|
||||
return dir_t(m_fs.open_directory((u32) key));
|
||||
}
|
||||
|
||||
}
|
160
src/lib/formats/fs_coco_os9.h
Normal file
160
src/lib/formats/fs_coco_os9.h
Normal file
@ -0,0 +1,160 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Nathan Woods
|
||||
/***************************************************************************
|
||||
|
||||
fs_coco_os9.h
|
||||
|
||||
Management of CoCo OS-9 floppy images
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_FORMATS_FS_COCO_OS9_H
|
||||
#define MAME_FORMATS_FS_COCO_OS9_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fsmgr.h"
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
namespace fs {
|
||||
|
||||
// ======================> coco_os9_image
|
||||
|
||||
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); }
|
||||
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 *description() const override;
|
||||
|
||||
virtual void enumerate_f(floppy_enumerator &fe, u32 form_factor, const std::vector<u32> &variants) const override;
|
||||
virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override;
|
||||
|
||||
virtual bool can_format() const override;
|
||||
virtual bool can_read() const override;
|
||||
virtual bool can_write() const override;
|
||||
virtual bool has_rsrc() const override;
|
||||
virtual char directory_separator() 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> 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;
|
||||
|
||||
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 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;
|
||||
|
||||
} // namespace fs
|
||||
|
||||
#endif // MAME_FORMATS_FS_COCO_OS9_H
|
@ -26,6 +26,8 @@ const char *meta_data::entry_name(meta_name name)
|
||||
case meta_name::size_in_blocks: return "size_in_blocks";
|
||||
case meta_name::file_type: return "file_type";
|
||||
case meta_name::ascii_flag: return "ascii_flag";
|
||||
case meta_name::owner_id: return "owner_id";
|
||||
case meta_name::attributes: return "attributes";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@ -32,7 +32,9 @@ enum class meta_name {
|
||||
sequential,
|
||||
size_in_blocks,
|
||||
file_type,
|
||||
ascii_flag
|
||||
ascii_flag,
|
||||
owner_id,
|
||||
attributes
|
||||
};
|
||||
|
||||
enum class meta_type {
|
||||
|
@ -216,49 +216,49 @@ void fsblk_t::block_t::w32l(u32 offset, u32 data)
|
||||
blk[3] = data >> 24;
|
||||
}
|
||||
|
||||
std::string fsblk_t::block_t::rstr(u32 offset, u32 size)
|
||||
std::string fsblk_t::block_t::rstr(u32 offset, u32 size) const
|
||||
{
|
||||
const u8 *d = m_object->rooffset("rstr", offset, size);
|
||||
return std::string(d, d + size);
|
||||
}
|
||||
|
||||
u8 fsblk_t::block_t::r8(u32 offset)
|
||||
u8 fsblk_t::block_t::r8(u32 offset) const
|
||||
{
|
||||
const u8 *blk = m_object->offset("r8", offset, 1);
|
||||
return blk[0];
|
||||
}
|
||||
|
||||
u16 fsblk_t::block_t::r16b(u32 offset)
|
||||
u16 fsblk_t::block_t::r16b(u32 offset) const
|
||||
{
|
||||
const u8 *blk = m_object->offset("r16b", offset, 2);
|
||||
return (blk[0] << 8) | blk[1];
|
||||
}
|
||||
|
||||
u32 fsblk_t::block_t::r24b(u32 offset)
|
||||
u32 fsblk_t::block_t::r24b(u32 offset) const
|
||||
{
|
||||
const u8 *blk = m_object->offset("r24b", offset, 3);
|
||||
return (blk[0] << 16) | (blk[1] << 8) | blk[2];
|
||||
}
|
||||
|
||||
u32 fsblk_t::block_t::r32b(u32 offset)
|
||||
u32 fsblk_t::block_t::r32b(u32 offset) const
|
||||
{
|
||||
const u8 *blk = m_object->offset("r32b", offset, 4);
|
||||
return (blk[0] << 24) | (blk[1] << 16) | (blk[2] << 8) | blk[3];
|
||||
}
|
||||
|
||||
u16 fsblk_t::block_t::r16l(u32 offset)
|
||||
u16 fsblk_t::block_t::r16l(u32 offset) const
|
||||
{
|
||||
const u8 *blk = m_object->offset("r16l", offset, 2);
|
||||
return blk[0] | (blk[1] << 8);
|
||||
}
|
||||
|
||||
u32 fsblk_t::block_t::r24l(u32 offset)
|
||||
u32 fsblk_t::block_t::r24l(u32 offset) const
|
||||
{
|
||||
const u8 *blk = m_object->offset("r24l", offset, 3);
|
||||
return blk[0] | (blk[1] << 8) | (blk[2] << 16);
|
||||
}
|
||||
|
||||
u32 fsblk_t::block_t::r32l(u32 offset)
|
||||
u32 fsblk_t::block_t::r32l(u32 offset) const
|
||||
{
|
||||
const u8 *blk = m_object->offset("r32l", offset, 4);
|
||||
return blk[0] | (blk[1] << 8) | (blk[2] << 16) | (blk[3] << 24);
|
||||
|
@ -158,7 +158,9 @@ public:
|
||||
block_t strong() { return block_t(m_object, false); }
|
||||
block_t weak() { return block_t(m_object, true); }
|
||||
|
||||
const u8 *rodata() { return m_object->rodata(); }
|
||||
u32 size() const { return m_object->size(); }
|
||||
|
||||
const u8 *rodata() const { return m_object->rodata(); }
|
||||
u8 *data() { return m_object->data(); }
|
||||
|
||||
void copy(u32 offset, const u8 *src, u32 size);
|
||||
@ -173,14 +175,14 @@ public:
|
||||
void w24l(u32 offset, u32 data);
|
||||
void w32l(u32 offset, u32 data);
|
||||
|
||||
std::string rstr(u32 offset, u32 size);
|
||||
u8 r8( u32 offset);
|
||||
u16 r16b(u32 offset);
|
||||
u32 r24b(u32 offset);
|
||||
u32 r32b(u32 offset);
|
||||
u16 r16l(u32 offset);
|
||||
u32 r24l(u32 offset);
|
||||
u32 r32l(u32 offset);
|
||||
std::string rstr(u32 offset, u32 size) const;
|
||||
u8 r8( u32 offset) const;
|
||||
u16 r16b(u32 offset) const;
|
||||
u32 r24b(u32 offset) const;
|
||||
u32 r32b(u32 offset) const;
|
||||
u16 r16l(u32 offset) const;
|
||||
u32 r24l(u32 offset) const;
|
||||
u32 r32l(u32 offset) const;
|
||||
};
|
||||
|
||||
fsblk_t() : m_block_size(0) {}
|
||||
|
@ -271,6 +271,8 @@ static void dir_scan(u32 depth, fs::filesystem_t::dir_t dir, std::vector<std::ve
|
||||
case fs::dir_entry_type::dir: {
|
||||
auto subdir = dir.dir_get(c.m_key);
|
||||
auto meta = subdir.metadata();
|
||||
if (!meta.has(fs::meta_name::name))
|
||||
meta.set(fs::meta_name::name, c.m_name);
|
||||
for(const auto &m : dmetad) {
|
||||
if(!meta.has(m.m_name))
|
||||
continue;
|
||||
@ -287,6 +289,8 @@ static void dir_scan(u32 depth, fs::filesystem_t::dir_t dir, std::vector<std::ve
|
||||
case fs::dir_entry_type::system_file: {
|
||||
auto file = dir.file_get(c.m_key);
|
||||
auto meta = file.metadata();
|
||||
if (!meta.has(fs::meta_name::name))
|
||||
meta.set(fs::meta_name::name, c.m_name);
|
||||
for(const auto &m : fmetad) {
|
||||
if(!meta.has(m.m_name))
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user