mirror of
https://github.com/holub/mame
synced 2025-04-16 21:44:32 +03:00
Reimplemented support for the CoCo's RS-DOS filesystem on top of the "fsmgr" framework (currently read only) (#9080)
* Reimplemented support for the CoCo's RS-DOS filesystem on top of the "fsmgr" framework (currently read only) * Added support for file_type and ascii_flag metadata, minor bug fix decoding file allocation table entries * Creating a "CoCo Raw Disk" format and changing the CoCo RS-DOS filesystem to use it * 1. Adding COCO_RAWDSK to all.cpp 2. Fixing sector order on CoCo raw disk
This commit is contained in:
parent
53d6b930ef
commit
fbff8a2483
@ -563,6 +563,18 @@ if opt_tool(FORMATS, "COCO_CAS") then
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
--
|
||||||
|
--@src/lib/formats/coco_rawdsk.h,FORMATS["COCO_RAWDSK"] = true
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
if opt_tool(FORMATS, "COCO_RAWDSK") then
|
||||||
|
files {
|
||||||
|
MAME_DIR.. "src/lib/formats/coco_rawdsk.cpp",
|
||||||
|
MAME_DIR.. "src/lib/formats/coco_rawdsk.h",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
--
|
--
|
||||||
--@src/lib/formats/comx35_dsk.h,FORMATS["COMX35_DSK"] = true
|
--@src/lib/formats/comx35_dsk.h,FORMATS["COMX35_DSK"] = true
|
||||||
@ -2100,4 +2112,16 @@ if opt_tool(FORMATS, "FS_ORIC_JASMIN") then
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
--
|
||||||
|
--@src/lib/formats/fs_coco_rsdos.h,FORMATS["FS_COCO_RSDOS"] = true
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
if opt_tool(FORMATS, "FS_COCO_RSDOS") then
|
||||||
|
files {
|
||||||
|
MAME_DIR.. "src/lib/formats/fs_coco_rsdos.cpp",
|
||||||
|
MAME_DIR.. "src/lib/formats/fs_coco_rsdos.h",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1184,6 +1184,7 @@ FORMATS["XDF_DSK"] = true
|
|||||||
FORMATS["ZX81_P"] = true
|
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
|
||||||
|
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
-- this is the list of driver libraries that
|
-- this is the list of driver libraries that
|
||||||
|
@ -356,6 +356,14 @@
|
|||||||
#include "os9_dsk.h"
|
#include "os9_dsk.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_FORMATS_COCO_RAWDSK
|
||||||
|
#include "coco_rawdsk.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_FORMATS_FS_COCO_RSDOS
|
||||||
|
#include "fs_coco_rsdos.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_FORMATS_JFD_DSK
|
#ifdef HAS_FORMATS_JFD_DSK
|
||||||
#include "jfd_dsk.h"
|
#include "jfd_dsk.h"
|
||||||
#endif
|
#endif
|
||||||
@ -1071,6 +1079,12 @@ void mame_formats_full_list(mame_formats_enumerator &en)
|
|||||||
en.add(FLOPPY_JV1_FORMAT); // trs80_dsk.h
|
en.add(FLOPPY_JV1_FORMAT); // trs80_dsk.h
|
||||||
en.add(FLOPPY_JV3_FORMAT); // trs80_dsk.h
|
en.add(FLOPPY_JV3_FORMAT); // trs80_dsk.h
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAS_FORMATS_COCO_RAWDSK
|
||||||
|
en.add(FLOPPY_COCO_RAWDSK_FORMAT); // coco_rawdsk.h
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_FORMATS_FS_COCO_RSDOS
|
||||||
|
en.add(fs::COCO_RSDOS); // fs_coco_rsdos.h
|
||||||
|
#endif
|
||||||
|
|
||||||
en.category("Kaypro");
|
en.category("Kaypro");
|
||||||
#ifdef HAS_FORMATS_KAYPRO_DSK
|
#ifdef HAS_FORMATS_KAYPRO_DSK
|
||||||
|
45
src/lib/formats/coco_rawdsk.cpp
Normal file
45
src/lib/formats/coco_rawdsk.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Nathan Woods
|
||||||
|
/***************************************************************************
|
||||||
|
|
||||||
|
CoCo Raw Disk
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "coco_rawdsk.h"
|
||||||
|
|
||||||
|
|
||||||
|
coco_rawdsk_format::coco_rawdsk_format() : wd177x_format(formats)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *coco_rawdsk_format::name() const
|
||||||
|
{
|
||||||
|
return "coco_rawdsk";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *coco_rawdsk_format::description() const
|
||||||
|
{
|
||||||
|
return "CoCo Raw Disk";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *coco_rawdsk_format::extensions() const
|
||||||
|
{
|
||||||
|
return "raw";
|
||||||
|
}
|
||||||
|
|
||||||
|
const coco_rawdsk_format::format coco_rawdsk_format::formats[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
floppy_image::FF_525, floppy_image::SSDD, floppy_image::MFM,
|
||||||
|
2000, 18, 35, 1, 256, {}, -1, { 1,12,5,16,9,2,13,6,17,10,3,14,7,18,11,4,15,8 }, 32, 22, 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
floppy_image::FF_525, floppy_image::SSDD, floppy_image::MFM,
|
||||||
|
2000, 18, 40, 1, 256, {}, -1, { 1,12,5,16,9,2,13,6,17,10,3,14,7,18,11,4,15,8 }, 32, 22, 24
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const floppy_format_type FLOPPY_COCO_RAWDSK_FORMAT = &floppy_image_format_creator<coco_rawdsk_format>;
|
33
src/lib/formats/coco_rawdsk.h
Normal file
33
src/lib/formats/coco_rawdsk.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Nathan Woods
|
||||||
|
/***************************************************************************
|
||||||
|
|
||||||
|
CoCo Raw Disk
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAME_FORMATS_COCO_RAWDSK_H
|
||||||
|
#define MAME_FORMATS_COCO_RAWDSK_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wd177x_dsk.h"
|
||||||
|
|
||||||
|
|
||||||
|
class coco_rawdsk_format : public wd177x_format
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
coco_rawdsk_format();
|
||||||
|
|
||||||
|
virtual const char *name() const override;
|
||||||
|
virtual const char *description() const override;
|
||||||
|
virtual const char *extensions() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const format formats[];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern const floppy_format_type FLOPPY_COCO_RAWDSK_FORMAT;
|
||||||
|
|
||||||
|
#endif // MAME_FORMATS_COCO_RAWDSK_H
|
297
src/lib/formats/fs_coco_rsdos.cpp
Normal file
297
src/lib/formats/fs_coco_rsdos.cpp
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Nathan Woods
|
||||||
|
/***************************************************************************
|
||||||
|
|
||||||
|
fs_coco_rsdos.cpp
|
||||||
|
|
||||||
|
Management of CoCo "RS-DOS" floppy images
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "fs_coco_rsdos.h"
|
||||||
|
#include "coco_rawdsk.h"
|
||||||
|
#include "util/corestr.h"
|
||||||
|
#include "util/strformat.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace fs {
|
||||||
|
|
||||||
|
const coco_rsdos_image COCO_RSDOS;
|
||||||
|
|
||||||
|
const char *coco_rsdos_image::name() const
|
||||||
|
{
|
||||||
|
return "coco_rsdos";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *coco_rsdos_image::description() const
|
||||||
|
{
|
||||||
|
return "CoCo RS-DOS";
|
||||||
|
}
|
||||||
|
|
||||||
|
void coco_rsdos_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_rsdos_35", "CoCo Raw Disk RS-DOS single-sided 35 tracks");
|
||||||
|
fe.add(FLOPPY_COCO_RAWDSK_FORMAT, 184320, "coco_rawdsk_rsdos_40", "CoCo Raw Disk RS-DOS single-sided 40 tracks");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool coco_rsdos_image::can_format() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool coco_rsdos_image::can_read() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool coco_rsdos_image::can_write() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool coco_rsdos_image::has_rsrc() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<meta_description> coco_rsdos_image::file_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, 8.3"));
|
||||||
|
results.emplace_back(meta_description(meta_name::file_type, meta_type::number, 0, true, nullptr, "Type of the file"));
|
||||||
|
results.emplace_back(meta_description(meta_name::ascii_flag, meta_type::string, 0, true, nullptr, "Ascii or binary flag"));
|
||||||
|
results.emplace_back(meta_description(meta_name::size_in_blocks, meta_type::number, 0, true, nullptr, "Number of granules used by the file"));
|
||||||
|
results.emplace_back(meta_description(meta_name::length, meta_type::number, 0, true, nullptr, "Size of the file in bytes"));
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<filesystem_t> coco_rsdos_image::mount(fsblk_t &blockdev) const
|
||||||
|
{
|
||||||
|
return std::make_unique<impl>(blockdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool coco_rsdos_image::validate_filename(std::string_view name)
|
||||||
|
{
|
||||||
|
auto pos = name.find('.');
|
||||||
|
auto stem_length = pos != std::string::npos ? pos : name.size();
|
||||||
|
auto ext_length = pos != std::string::npos ? name.size() - pos - 1 : 0;
|
||||||
|
return stem_length > 0 && stem_length <= 8 && ext_length <= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
coco_rsdos_image::impl::impl(fsblk_t &blockdev)
|
||||||
|
: filesystem_t(blockdev, 256)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_data coco_rsdos_image::impl::metadata()
|
||||||
|
{
|
||||||
|
return meta_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
filesystem_t::dir_t coco_rsdos_image::impl::root()
|
||||||
|
{
|
||||||
|
if (!m_root)
|
||||||
|
m_root = new root_dir(*this);
|
||||||
|
return m_root.strong();
|
||||||
|
}
|
||||||
|
|
||||||
|
void coco_rsdos_image::impl::drop_root_ref()
|
||||||
|
{
|
||||||
|
m_root = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
fsblk_t::block_t coco_rsdos_image::impl::read_sector(int track, int sector) const
|
||||||
|
{
|
||||||
|
// the CoCo RS-DOS world thinks in terms of tracks/sectors, but we have a block device
|
||||||
|
// abstraction
|
||||||
|
return m_blockdev.get(track * 18 + sector - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 coco_rsdos_image::impl::maximum_granules() const
|
||||||
|
{
|
||||||
|
u32 sector_count = m_blockdev.block_count();
|
||||||
|
u32 granule_count = (sector_count / 9) - 2;
|
||||||
|
return granule_count <= 0xFF ? (u8)granule_count : 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string coco_rsdos_image::impl::get_filename_from_dirent(const rsdos_dirent &dirent)
|
||||||
|
{
|
||||||
|
std::string_view stem = strtrimrightspace(std::string_view(&dirent.m_filename[0], 8));
|
||||||
|
std::string_view ext = strtrimrightspace(std::string_view(&dirent.m_filename[8], 3));
|
||||||
|
return util::string_format("%s.%s", stem, ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
void coco_rsdos_image::impl::root_dir::drop_weak_references()
|
||||||
|
{
|
||||||
|
m_fs.drop_root_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_data coco_rsdos_image::impl::root_dir::metadata()
|
||||||
|
{
|
||||||
|
return meta_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<dir_entry> coco_rsdos_image::impl::root_dir::contents()
|
||||||
|
{
|
||||||
|
u64 key = 0;
|
||||||
|
std::vector<dir_entry> results;
|
||||||
|
for (int dir_sector = 3; dir_sector <= 18; dir_sector++)
|
||||||
|
{
|
||||||
|
// read this directory sector
|
||||||
|
auto dir_block = m_fs.read_sector(17, dir_sector);
|
||||||
|
const rsdos_dirent_sector §or = *reinterpret_cast<const rsdos_dirent_sector *>(dir_block.rodata());
|
||||||
|
|
||||||
|
// and loop through all entries
|
||||||
|
for (const auto &ent : sector.m_entries)
|
||||||
|
{
|
||||||
|
// 0xFF marks the end of the directory
|
||||||
|
if (ent.m_dirent.m_filename[0] == '\xFF')
|
||||||
|
return results;
|
||||||
|
|
||||||
|
// 0x00 marks a deleted file
|
||||||
|
if (ent.m_dirent.m_filename[0] != '\0')
|
||||||
|
results.emplace_back(get_filename_from_dirent(ent.m_dirent), dir_entry_type::file, key);
|
||||||
|
|
||||||
|
key++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
filesystem_t::file_t coco_rsdos_image::impl::root_dir::file_get(u64 key)
|
||||||
|
{
|
||||||
|
auto dir_block = m_fs.read_sector(17, 3 + key / 4);
|
||||||
|
const rsdos_dirent_sector §or = *reinterpret_cast<const rsdos_dirent_sector *>(dir_block.rodata());
|
||||||
|
const rsdos_dirent &ent = sector.m_entries[key % 4].m_dirent;
|
||||||
|
return file_t(new file(m_fs, rsdos_dirent(ent)));
|
||||||
|
}
|
||||||
|
|
||||||
|
filesystem_t::dir_t coco_rsdos_image::impl::root_dir::dir_get(u64 key)
|
||||||
|
{
|
||||||
|
throw std::logic_error("Directories not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
coco_rsdos_image::impl::granule_iterator::granule_iterator(impl &fs, const rsdos_dirent &dirent)
|
||||||
|
: m_granule_map(fs.read_sector(17, 2))
|
||||||
|
, m_current_granule(dirent.m_first_granule)
|
||||||
|
, m_maximum_granules(fs.maximum_granules())
|
||||||
|
, m_last_sector_bytes(((u16) dirent.m_last_sector_bytes_msb << 8) | dirent.m_last_sector_bytes_lsb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool coco_rsdos_image::impl::granule_iterator::next(u8 &granule, u16 &byte_count)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
granule = ~0;
|
||||||
|
byte_count = 0;
|
||||||
|
|
||||||
|
if (m_current_granule)
|
||||||
|
{
|
||||||
|
const u8 *granule_map_data = m_granule_map.rodata();
|
||||||
|
if (granule_map_data[*m_current_granule] < m_maximum_granules)
|
||||||
|
{
|
||||||
|
// this entry points to the next granule
|
||||||
|
success = true;
|
||||||
|
granule = *m_current_granule;
|
||||||
|
byte_count = 9 * 256;
|
||||||
|
m_current_granule = granule_map_data[*m_current_granule];
|
||||||
|
}
|
||||||
|
else if (granule_map_data[*m_current_granule] >= 0xC0 && granule_map_data[*m_current_granule] <= 0xC9)
|
||||||
|
{
|
||||||
|
// this is the last granule in the file
|
||||||
|
success = true;
|
||||||
|
granule = *m_current_granule;
|
||||||
|
u16 sector_count = std::max(granule_map_data[*m_current_granule], (u8)0xC1) - 0xC1;
|
||||||
|
byte_count = sector_count * 256 + m_last_sector_bytes;
|
||||||
|
m_current_granule = std::nullopt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// should not happen; but we'll treat this as an EOF
|
||||||
|
m_current_granule = std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
coco_rsdos_image::impl::file::file(impl &fs, rsdos_dirent &&dirent)
|
||||||
|
: m_fs(fs)
|
||||||
|
, m_dirent(std::move(dirent))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void coco_rsdos_image::impl::file::drop_weak_references()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_data coco_rsdos_image::impl::file::metadata()
|
||||||
|
{
|
||||||
|
u32 file_size = 0;
|
||||||
|
int granule_count = 0;
|
||||||
|
|
||||||
|
// we need to iterate on the file to determine the size and granule/block count
|
||||||
|
u8 granule;
|
||||||
|
u16 byte_count;
|
||||||
|
granule_iterator iter(m_fs, m_dirent);
|
||||||
|
while (iter.next(granule, byte_count))
|
||||||
|
{
|
||||||
|
granule_count++;
|
||||||
|
file_size += byte_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// turn the ASCII flag to a single character (this reflects what the user sees when doing a directory listing on a real CoCo)
|
||||||
|
char file_type_char = 'B' + m_dirent.m_asciiflag;
|
||||||
|
|
||||||
|
// build the metadata and return it
|
||||||
|
meta_data result;
|
||||||
|
result.set(meta_name::name, get_filename_from_dirent(m_dirent));
|
||||||
|
result.set(meta_name::file_type, m_dirent.m_filetype);
|
||||||
|
result.set(meta_name::ascii_flag, std::string(1, file_type_char));
|
||||||
|
result.set(meta_name::size_in_blocks, granule_count);
|
||||||
|
result.set(meta_name::length, file_size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> coco_rsdos_image::impl::file::read_all()
|
||||||
|
{
|
||||||
|
std::vector<u8> result;
|
||||||
|
|
||||||
|
u8 granule;
|
||||||
|
u16 byte_count;
|
||||||
|
granule_iterator iter(m_fs, m_dirent);
|
||||||
|
while (iter.next(granule, byte_count))
|
||||||
|
{
|
||||||
|
// resize the results
|
||||||
|
size_t current_size = result.size();
|
||||||
|
result.resize(current_size + byte_count);
|
||||||
|
|
||||||
|
// determine which track and sector this granule starts at
|
||||||
|
int track = granule / 2 + (granule >= 34 ? 1 : 0);
|
||||||
|
int sector = granule % 2 * 9 + 1;
|
||||||
|
|
||||||
|
// and read all the sectors
|
||||||
|
while (byte_count > 0)
|
||||||
|
{
|
||||||
|
// read this sector
|
||||||
|
auto block = m_fs.read_sector(track, sector);
|
||||||
|
const u8 *data = block.rodata();
|
||||||
|
u16 data_length = std::min(byte_count, (u16)256);
|
||||||
|
|
||||||
|
// and append it to the results
|
||||||
|
memcpy(result.data() + current_size, data, data_length);
|
||||||
|
|
||||||
|
// and advance
|
||||||
|
current_size += data_length;
|
||||||
|
byte_count -= data_length;
|
||||||
|
sector++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace fs
|
125
src/lib/formats/fs_coco_rsdos.h
Normal file
125
src/lib/formats/fs_coco_rsdos.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Nathan Woods
|
||||||
|
/***************************************************************************
|
||||||
|
|
||||||
|
fs_coco_rsdos.h
|
||||||
|
|
||||||
|
Management of CoCo "RS-DOS" floppy images
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAME_FORMATS_FS_COCO_RSDOS_H
|
||||||
|
#define MAME_FORMATS_FS_COCO_RSDOS_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fsmgr.h"
|
||||||
|
#include <optional>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace fs {
|
||||||
|
|
||||||
|
class coco_rsdos_image : public manager_t {
|
||||||
|
public:
|
||||||
|
coco_rsdos_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 std::vector<meta_description> file_meta_description() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class impl : public filesystem_t {
|
||||||
|
public:
|
||||||
|
class root_dir : public idir_t {
|
||||||
|
public:
|
||||||
|
root_dir(impl &i) : m_fs(i) {}
|
||||||
|
virtual ~root_dir() = 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rsdos_dirent
|
||||||
|
{
|
||||||
|
char m_filename[11];
|
||||||
|
u8 m_filetype;
|
||||||
|
u8 m_asciiflag;
|
||||||
|
u8 m_first_granule;
|
||||||
|
u8 m_last_sector_bytes_msb;
|
||||||
|
u8 m_last_sector_bytes_lsb;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rsdos_dirent_sector
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
rsdos_dirent m_dirent;
|
||||||
|
u8 m_unused[16];
|
||||||
|
} m_entries[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
class granule_iterator {
|
||||||
|
public:
|
||||||
|
granule_iterator(impl &fs, const rsdos_dirent &dirent);
|
||||||
|
bool next(u8 &granule, u16 &byte_count);
|
||||||
|
|
||||||
|
private:
|
||||||
|
fsblk_t::block_t m_granule_map;
|
||||||
|
std::optional<u8> m_current_granule;
|
||||||
|
u8 m_maximum_granules;
|
||||||
|
u16 m_last_sector_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
class file : public ifile_t {
|
||||||
|
public:
|
||||||
|
file(impl &fs, rsdos_dirent &&dirent);
|
||||||
|
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;
|
||||||
|
rsdos_dirent m_dirent;
|
||||||
|
};
|
||||||
|
|
||||||
|
impl(fsblk_t &blockdev);
|
||||||
|
virtual ~impl() = default;
|
||||||
|
|
||||||
|
virtual meta_data metadata() override;
|
||||||
|
virtual dir_t root() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
dir_t m_root;
|
||||||
|
|
||||||
|
void drop_root_ref();
|
||||||
|
fsblk_t::block_t read_sector(int track, int sector) const;
|
||||||
|
u8 maximum_granules() const;
|
||||||
|
static std::string get_filename_from_dirent(const rsdos_dirent &dirent);
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool validate_filename(std::string_view name);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const coco_rsdos_image COCO_RSDOS;
|
||||||
|
|
||||||
|
} // namespace fs
|
||||||
|
|
||||||
|
#endif // MAME_FORMATS_FS_COCO_RSDOS_H
|
@ -24,6 +24,8 @@ const char *meta_data::entry_name(meta_name name)
|
|||||||
case meta_name::rsrc_length: return "rsrc_length";
|
case meta_name::rsrc_length: return "rsrc_length";
|
||||||
case meta_name::sequential: return "sequential";
|
case meta_name::sequential: return "sequential";
|
||||||
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::ascii_flag: return "ascii_flag";
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ enum class meta_name {
|
|||||||
rsrc_length,
|
rsrc_length,
|
||||||
sequential,
|
sequential,
|
||||||
size_in_blocks,
|
size_in_blocks,
|
||||||
|
file_type,
|
||||||
|
ascii_flag
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class meta_type {
|
enum class meta_type {
|
||||||
|
Loading…
Reference in New Issue
Block a user