diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua index 686c5c32e9f..66db5fd78d0 100644 --- a/scripts/src/formats.lua +++ b/scripts/src/formats.lua @@ -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 diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 5174922f8dc..07f55663b4a 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -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 diff --git a/src/lib/formats/all.cpp b/src/lib/formats/all.cpp index 692977d4d03..aa3d9ab8d70 100644 --- a/src/lib/formats/all.cpp +++ b/src/lib/formats/all.cpp @@ -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 diff --git a/src/lib/formats/fs_coco_os9.cpp b/src/lib/formats/fs_coco_os9.cpp new file mode 100644 index 00000000000..aeacaf66d36 --- /dev/null +++ b/src/lib/formats/fs_coco_os9.cpp @@ -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 &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 coco_os9_image::volume_meta_description() const +{ + std::vector 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 coco_os9_image::file_meta_description() const +{ + return entity_meta_description(); +} + + +//------------------------------------------------- +// directory_meta_description +//------------------------------------------------- + +std::vector coco_os9_image::directory_meta_description() const +{ + return entity_meta_description(); +} + + +//------------------------------------------------- +// entity_meta_description +//------------------------------------------------- + +std::vector coco_os9_image::entity_meta_description() const +{ + std::vector 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 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(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 coco_os9_image::impl::read_file_data(const file_header &header) const +{ + std::vector 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 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 coco_os9_image::impl::directory::contents() +{ + // read the directory data + std::vector directory_data = m_fs.read_file_data(m_file_header); + + // and assemble results + std::vector 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)); +} + +} diff --git a/src/lib/formats/fs_coco_os9.h b/src/lib/formats/fs_coco_os9.h new file mode 100644 index 00000000000..dce2439694c --- /dev/null +++ b/src/lib/formats/fs_coco_os9.h @@ -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 +#include + +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 &variants) const override; + virtual std::unique_ptr 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 volume_meta_description() const override; + virtual std::vector file_meta_description() const override; + virtual std::vector directory_meta_description() const override; + std::vector 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 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 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 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 diff --git a/src/lib/formats/fsmeta.cpp b/src/lib/formats/fsmeta.cpp index 0159269a0d6..9ccb7e144b3 100644 --- a/src/lib/formats/fsmeta.cpp +++ b/src/lib/formats/fsmeta.cpp @@ -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 ""; } diff --git a/src/lib/formats/fsmeta.h b/src/lib/formats/fsmeta.h index 948df0c1f06..12ca8ef8e1a 100644 --- a/src/lib/formats/fsmeta.h +++ b/src/lib/formats/fsmeta.h @@ -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 { diff --git a/src/lib/formats/fsmgr.cpp b/src/lib/formats/fsmgr.cpp index 185c08fa503..3f37c79691a 100644 --- a/src/lib/formats/fsmgr.cpp +++ b/src/lib/formats/fsmgr.cpp @@ -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); diff --git a/src/lib/formats/fsmgr.h b/src/lib/formats/fsmgr.h index 37ddaac2265..376f7f35fe5 100644 --- a/src/lib/formats/fsmgr.h +++ b/src/lib/formats/fsmgr.h @@ -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) {} diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp index 76b24095e8c..7e452cb6997 100644 --- a/src/tools/floptool.cpp +++ b/src/tools/floptool.cpp @@ -271,6 +271,8 @@ static void dir_scan(u32 depth, fs::filesystem_t::dir_t dir, std::vector