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:
npwoods 2022-01-07 12:04:07 -05:00 committed by GitHub
parent 3abc1a4805
commit fd73621285
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 750 additions and 18 deletions

View File

@ -2124,4 +2124,16 @@ if opt_tool(FORMATS, "FS_COCO_RSDOS") then
} }
end 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 end

View File

@ -1185,6 +1185,7 @@ FORMATS["ZX81_P"] = true
FORMATS["FS_PRODOS"] = true FORMATS["FS_PRODOS"] = true
FORMATS["FS_ORIC_JASMIN"] = true FORMATS["FS_ORIC_JASMIN"] = true
FORMATS["FS_COCO_RSDOS"] = true FORMATS["FS_COCO_RSDOS"] = true
FORMATS["FS_COCO_OS9"] = true
-------------------------------------------------- --------------------------------------------------
-- this is the list of driver libraries that -- this is the list of driver libraries that

View File

@ -364,6 +364,10 @@
#include "fs_coco_rsdos.h" #include "fs_coco_rsdos.h"
#endif #endif
#ifdef HAS_FORMATS_FS_COCO_OS9
#include "fs_coco_os9.h"
#endif
#ifdef HAS_FORMATS_JFD_DSK #ifdef HAS_FORMATS_JFD_DSK
#include "jfd_dsk.h" #include "jfd_dsk.h"
#endif #endif
@ -1085,6 +1089,9 @@ void mame_formats_full_list(mame_formats_enumerator &en)
#ifdef HAS_FORMATS_FS_COCO_RSDOS #ifdef HAS_FORMATS_FS_COCO_RSDOS
en.add(fs::COCO_RSDOS); // fs_coco_rsdos.h en.add(fs::COCO_RSDOS); // fs_coco_rsdos.h
#endif #endif
#ifdef HAS_FORMATS_FS_COCO_OS9
en.add(fs::COCO_OS9); // fs_coco_os9.h
#endif
en.category("Kaypro"); en.category("Kaypro");
#ifdef HAS_FORMATS_KAYPRO_DSK #ifdef HAS_FORMATS_KAYPRO_DSK

View 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));
}
}

View 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

View File

@ -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::size_in_blocks: return "size_in_blocks";
case meta_name::file_type: return "file_type"; case meta_name::file_type: return "file_type";
case meta_name::ascii_flag: return "ascii_flag"; case meta_name::ascii_flag: return "ascii_flag";
case meta_name::owner_id: return "owner_id";
case meta_name::attributes: return "attributes";
} }
return ""; return "";
} }

View File

@ -32,7 +32,9 @@ enum class meta_name {
sequential, sequential,
size_in_blocks, size_in_blocks,
file_type, file_type,
ascii_flag ascii_flag,
owner_id,
attributes
}; };
enum class meta_type { enum class meta_type {

View File

@ -216,49 +216,49 @@ void fsblk_t::block_t::w32l(u32 offset, u32 data)
blk[3] = data >> 24; 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); const u8 *d = m_object->rooffset("rstr", offset, size);
return std::string(d, d + 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); const u8 *blk = m_object->offset("r8", offset, 1);
return blk[0]; 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); const u8 *blk = m_object->offset("r16b", offset, 2);
return (blk[0] << 8) | blk[1]; 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); const u8 *blk = m_object->offset("r24b", offset, 3);
return (blk[0] << 16) | (blk[1] << 8) | blk[2]; 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); const u8 *blk = m_object->offset("r32b", offset, 4);
return (blk[0] << 24) | (blk[1] << 16) | (blk[2] << 8) | blk[3]; 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); const u8 *blk = m_object->offset("r16l", offset, 2);
return blk[0] | (blk[1] << 8); 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); const u8 *blk = m_object->offset("r24l", offset, 3);
return blk[0] | (blk[1] << 8) | (blk[2] << 16); 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); const u8 *blk = m_object->offset("r32l", offset, 4);
return blk[0] | (blk[1] << 8) | (blk[2] << 16) | (blk[3] << 24); return blk[0] | (blk[1] << 8) | (blk[2] << 16) | (blk[3] << 24);

View File

@ -158,7 +158,9 @@ public:
block_t strong() { return block_t(m_object, false); } block_t strong() { return block_t(m_object, false); }
block_t weak() { return block_t(m_object, true); } 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(); } u8 *data() { return m_object->data(); }
void copy(u32 offset, const u8 *src, u32 size); void copy(u32 offset, const u8 *src, u32 size);
@ -173,14 +175,14 @@ public:
void w24l(u32 offset, u32 data); void w24l(u32 offset, u32 data);
void w32l(u32 offset, u32 data); void w32l(u32 offset, u32 data);
std::string rstr(u32 offset, u32 size); std::string rstr(u32 offset, u32 size) const;
u8 r8( u32 offset); u8 r8( u32 offset) const;
u16 r16b(u32 offset); u16 r16b(u32 offset) const;
u32 r24b(u32 offset); u32 r24b(u32 offset) const;
u32 r32b(u32 offset); u32 r32b(u32 offset) const;
u16 r16l(u32 offset); u16 r16l(u32 offset) const;
u32 r24l(u32 offset); u32 r24l(u32 offset) const;
u32 r32l(u32 offset); u32 r32l(u32 offset) const;
}; };
fsblk_t() : m_block_size(0) {} fsblk_t() : m_block_size(0) {}

View File

@ -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: { case fs::dir_entry_type::dir: {
auto subdir = dir.dir_get(c.m_key); auto subdir = dir.dir_get(c.m_key);
auto meta = subdir.metadata(); 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) { for(const auto &m : dmetad) {
if(!meta.has(m.m_name)) if(!meta.has(m.m_name))
continue; 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: { case fs::dir_entry_type::system_file: {
auto file = dir.file_get(c.m_key); auto file = dir.file_get(c.m_key);
auto meta = file.metadata(); 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) { for(const auto &m : fmetad) {
if(!meta.has(m.m_name)) if(!meta.has(m.m_name))
continue; continue;