summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/fs_cbmdos.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats/fs_cbmdos.cpp')
-rw-r--r--src/lib/formats/fs_cbmdos.cpp433
1 files changed, 389 insertions, 44 deletions
diff --git a/src/lib/formats/fs_cbmdos.cpp b/src/lib/formats/fs_cbmdos.cpp
index 51d1369b04f..44c810a04a6 100644
--- a/src/lib/formats/fs_cbmdos.cpp
+++ b/src/lib/formats/fs_cbmdos.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
+// copyright-holders:Nathan Woods, Wilbert Pol
/***************************************************************************
fs_cbmdos.cpp
@@ -8,21 +8,30 @@
http://fileformats.archiveteam.org/wiki/CBMFS
+Current limitations:
+- Writing is limited to the first 35 tracks.
+- Determine or select the file type. Currently defaulting to PRG; 0 byte files
+ will be assigned file type DEL.
+
***************************************************************************/
#include "fs_cbmdos.h"
+
#include "d64_dsk.h"
#include "fsblk.h"
#include "corestr.h"
+#include "multibyte.h"
#include "strformat.h"
#include <array>
#include <optional>
+#include <regex>
#include <set>
#include <string_view>
#include <tuple>
+
namespace fs {
const cbmdos_image CBMDOS;
};
@@ -33,6 +42,8 @@ namespace {
class impl : public filesystem_t {
public:
+ static constexpr u8 SECTOR_DIRECTORY_COUNT = 8;
+
struct cbmdos_dirent
{
u8 m_next_directory_track;
@@ -55,30 +66,74 @@ public:
block_iterator(const impl &fs, u8 first_track, u8 first_sector);
bool next();
const void *data() const;
- const std::array<cbmdos_dirent, 4> &dirent_data() const;
+ const std::array<cbmdos_dirent, SECTOR_DIRECTORY_COUNT> &dirent_data() const;
u8 size() const;
+ u8 track() const { return m_track; }
+ u8 sector() const { return m_sector; }
private:
const impl & m_fs;
- fsblk_t::block_t m_block;
+ fsblk_t::block_t::ptr m_block;
std::set<std::tuple<u8, u8>> m_visited_set;
u8 m_track;
u8 m_sector;
+ u8 m_next_track;
+ u8 m_next_sector;
};
impl(fsblk_t &blockdev);
virtual ~impl() = default;
virtual meta_data volume_metadata() override;
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::error_condition file_create(const std::vector<std::string> &path, const meta_data &meta) override;
+ virtual std::error_condition file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
private:
- fsblk_t::block_t read_sector(int track, int sector) const;
+ static constexpr u32 BLOCK_SIZE = 256;
+ static constexpr u8 DIRECTORY_ENTRY_SIZE = 0x20;
+ static constexpr u8 FILE_TYPE_DEL = 0x80;
+ static constexpr u8 FILE_TYPE_SEQ = 0x81;
+ static constexpr u8 FILE_TYPE_PRG = 0x82;
+ static constexpr u8 FILE_TYPE_USR = 0x83;
+ static constexpr u8 FILE_TYPE_REL = 0x84;
+ static constexpr u8 TRACK_VARIANTS = 5;
+ static constexpr u8 MAX_SECTORS = 21;
+ static constexpr u8 MAX_TRACKS = 40;
+ static constexpr u8 DIRECTORY_TRACK = 18;
+ static constexpr u8 BAM_SECTOR = 0;
+ static constexpr u8 FIRST_DIRECTORY_SECTOR = 1;
+ static constexpr u8 SECTOR_DATA_BYTES = 254;
+ static constexpr u8 OFFSET_FILE_TYPE = 0x02;
+ static constexpr u8 OFFSET_FILE_FIRST_TRACK = 0x03;
+ static constexpr u8 OFFSET_FILE_FIRST_SECTOR = 0x04;
+ static constexpr u8 OFFSET_FILE_NAME = 0x05;
+ static constexpr u8 OFFSET_SECTOR_COUNT = 0x1e;
+ static constexpr u8 OFFSET_CHAIN_TRACK = 0x00;
+ static constexpr u8 OFFSET_CHAIN_SECTOR = 0x01;
+ static constexpr u8 CHAIN_END = 0x00;
+
+ static const struct smap
+ {
+ u8 first_track;
+ u8 last_track;
+ int sector[MAX_SECTORS];
+ } s_track_sector_map[TRACK_VARIANTS];
+ static const u8 s_data_track_order[MAX_TRACKS - 1];
+ u8 m_max_track;
+
+ fsblk_t::block_t::ptr read_sector(int track, int sector) const;
std::optional<cbmdos_dirent> dirent_from_path(const std::vector<std::string> &path) const;
- void iterate_directory_entries(const std::function<bool(const cbmdos_dirent &dirent)> &callback) const;
+ void iterate_directory_entries(const std::function<bool(u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)> &callback) const;
+ void iterate_all_directory_entries(const std::function<bool(u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)> &callback) const;
meta_data metadata_from_dirent(const cbmdos_dirent &dirent) const;
+ bool is_valid_filename(const std::string &filename) const;
+ std::pair<std::error_condition, u8> claim_track_sector(u8 track) const;
+ std::tuple<std::error_condition, u8, u8> claim_sector() const;
+ std::error_condition free_sector(u8 track, u8 sector) const;
+ u8 determine_file_type(const std::vector<u8> &data) const;
};
// methods
@@ -145,7 +200,7 @@ bool fs::cbmdos_image::can_read() const
bool fs::cbmdos_image::can_write() const
{
- return false;
+ return true;
}
@@ -223,8 +278,22 @@ std::string_view strtrimright_cbm(const char (&str)[N])
// impl ctor
//-------------------------------------------------
+const u8 impl::s_data_track_order[MAX_TRACKS - 1] = {
+ 17, 19, 16, 20, 15, 21, 14, 22, 13, 23, 12, 24, 11, 25, 10, 26, 9, 27, 8, 28, 7, 29, 6, 30, 5, 31, 4, 32, 3, 33, 2, 34, 1, 35, 36, 37, 38, 39, 40
+};
+
+const impl::smap impl::s_track_sector_map[TRACK_VARIANTS] = {
+ { 1, 17, { 0, 11, 1, 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10 } },
+ { 18, 18, { 0, 1, 4, 7, 10, 13, 16, 2, 5, 8, 11, 14, 17, 3, 6, 9, 12, 15, 18, -1, -1 } },
+ { 19, 24, { 0, 10, 1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6, 16, 7, 17, 8, 18, 9, -1, -1 } },
+ { 25, 30, { 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, 17, -1, -1, -1 } },
+ { 31, 40, { 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, -1, -1, -1, -1 } }
+};
+
+
impl::impl(fsblk_t &blockdev)
- : filesystem_t(blockdev, 256)
+ : filesystem_t(blockdev, BLOCK_SIZE)
+ , m_max_track(35)
{
}
@@ -235,8 +304,8 @@ impl::impl(fsblk_t &blockdev)
meta_data impl::volume_metadata()
{
- auto bam_block = read_sector(18, 0);
- std::string_view disk_name = std::string_view((const char *) bam_block.rodata() + 0x90, 16);
+ auto bam_block = read_sector(DIRECTORY_TRACK, BAM_SECTOR);
+ std::string_view disk_name = bam_block->rstr(0x90, 16);
meta_data results;
results.set(meta_name::name, strtrimright_cbm(disk_name));
@@ -248,13 +317,13 @@ meta_data impl::volume_metadata()
// impl::metadata
//-------------------------------------------------
-std::pair<err_t, meta_data> impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> impl::metadata(const std::vector<std::string> &path)
{
std::optional<cbmdos_dirent> dirent = dirent_from_path(path);
if (!dirent)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
- return std::make_pair(ERR_OK, metadata_from_dirent(*dirent));
+ return std::make_pair(std::error_condition(), metadata_from_dirent(*dirent));
}
@@ -262,16 +331,16 @@ std::pair<err_t, meta_data> impl::metadata(const std::vector<std::string> &path)
// impl::directory_contents
//-------------------------------------------------
-std::pair<err_t, std::vector<dir_entry>> impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> impl::directory_contents(const std::vector<std::string> &path)
{
std::vector<dir_entry> results;
- auto callback = [this, &results](const cbmdos_dirent &ent)
+ auto callback = [this, &results](u8 track, u8 sector, u8 file_index, const cbmdos_dirent &ent)
{
results.emplace_back(dir_entry_type::file, metadata_from_dirent(ent));
return false;
};
iterate_directory_entries(callback);
- return std::make_pair(ERR_OK, std::move(results));
+ return std::make_pair(std::error_condition(), std::move(results));
}
@@ -279,12 +348,12 @@ std::pair<err_t, std::vector<dir_entry>> impl::directory_contents(const std::vec
// impl::file_read
//-------------------------------------------------
-std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> impl::file_read(const std::vector<std::string> &path)
{
// find the file
std::optional<cbmdos_dirent> dirent = dirent_from_path(path);
if (!dirent)
- return std::make_pair(ERR_NOT_FOUND, std::vector<u8>());
+ return std::make_pair(error::not_found, std::vector<u8>());
// and get the data
std::vector<u8> result;
@@ -292,7 +361,263 @@ std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string>
while (iter.next())
result.insert(result.end(), (const u8 *)iter.data(), (const u8 *)iter.data() + iter.size());
- return std::make_pair(ERR_OK, std::move(result));
+ return std::make_pair(std::error_condition(), std::move(result));
+}
+
+
+std::error_condition impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
+{
+ std::string filename = meta.get_string(meta_name::name, "");
+ if (!is_valid_filename(filename))
+ return error::invalid_name;
+
+ std::optional<cbmdos_dirent> result;
+ u8 track = 0;
+ u8 sector = 0;
+ u8 file_index = 0;
+ auto callback = [&result, &track, &sector, &file_index](u8 t, u8 s, u8 i, const cbmdos_dirent &dirent)
+ {
+ bool found = dirent.m_file_type == 0x00;
+ if (found)
+ {
+ result = dirent;
+ track = t;
+ sector = s;
+ file_index = i;
+ }
+ return found;
+ };
+ iterate_all_directory_entries(callback);
+
+ if (!result)
+ {
+ // Claim a next directory sector
+ auto const [err, new_sector] = claim_track_sector(DIRECTORY_TRACK);
+ if (err)
+ return err;
+ auto new_block = read_sector(DIRECTORY_TRACK, new_sector);
+ for (int i = 2; i < BLOCK_SIZE; i++)
+ new_block->w8(i, 0);
+ // Find last directory sector
+ u8 last_sector = 0;
+ block_iterator iter(*this, DIRECTORY_TRACK, FIRST_DIRECTORY_SECTOR);
+ while (iter.next())
+ last_sector = iter.sector();
+ // Update chain on last directory sector
+ auto last_dir_block = read_sector(DIRECTORY_TRACK, last_sector);
+ last_dir_block->w8(OFFSET_CHAIN_TRACK, DIRECTORY_TRACK);
+ last_dir_block->w8(OFFSET_CHAIN_SECTOR, new_sector);
+ track = DIRECTORY_TRACK;
+ sector = new_sector;
+ }
+
+ auto const [err, file_track, file_sector] = claim_sector();
+ if (err)
+ return err;
+
+ // Create the file
+ auto dirblk = read_sector(track, sector);
+ u32 offset = file_index * DIRECTORY_ENTRY_SIZE;
+ for (int i = 0; i < DIRECTORY_ENTRY_SIZE; i++)
+ dirblk->w8(offset + i, (i >= 5 && i < 5 + 16) ? 0xa0 : 0x00);
+ dirblk->w8(offset + OFFSET_FILE_TYPE, FILE_TYPE_PRG);
+ dirblk->w8(offset + OFFSET_FILE_FIRST_TRACK, file_track);
+ dirblk->w8(offset + OFFSET_FILE_FIRST_SECTOR, file_sector);
+ dirblk->wstr(offset + OFFSET_FILE_NAME, filename);
+ // TODO set first side sector block track (rel file)
+ // TODO set first side sector block sector (rel file)
+ // TODO set rel file record length
+ // sector count will be set while writing the data
+
+ return std::error_condition();
+}
+
+
+std::error_condition impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
+{
+ if (path.size() != 1)
+ return error::not_found;
+ std::string_view path_part = path[0];
+
+ std::optional<cbmdos_dirent> result;
+ u8 dir_track = 0;
+ u8 dir_sector = 0;
+ u8 dir_file_index = 0;
+ auto const callback = [&result, &dir_track, &dir_sector, &dir_file_index, path_part] (u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)
+ {
+ bool found = strtrimright_cbm(dirent.m_file_name) == path_part;
+ if (found)
+ {
+ dir_track = track;
+ dir_sector = sector;
+ dir_file_index = file_index;
+ result = dirent;
+ }
+ return found;
+ };
+ iterate_directory_entries(callback);
+
+ if (!result)
+ return error::not_found;
+
+ u8 data_track = result->m_file_first_track;
+ u8 data_sector = result->m_file_first_sector;
+
+ const size_t data_length = data.size();
+ size_t offset = 0;
+ u32 sector_count = 0;
+ while (offset < data_length)
+ {
+ auto datablk = read_sector(data_track, data_sector);
+ u8 bytes = (data_length - offset) > SECTOR_DATA_BYTES ? SECTOR_DATA_BYTES : data_length - offset;
+ datablk->write(2, data.data() + offset, bytes);
+ offset += SECTOR_DATA_BYTES;
+ sector_count++;
+ if (datablk->r8(OFFSET_CHAIN_TRACK) == CHAIN_END)
+ {
+ if (offset < data_length)
+ {
+ auto [err, next_track, next_sector] = claim_sector();
+ if (err)
+ return err;
+ datablk->w8(OFFSET_CHAIN_TRACK, next_track);
+ datablk->w8(OFFSET_CHAIN_SECTOR, next_sector);
+ data_track = next_track;
+ data_sector = next_sector;
+ }
+ }
+ else
+ {
+ if (offset < data_length)
+ {
+ data_track = datablk->r8(OFFSET_CHAIN_TRACK);
+ data_sector = datablk->r8(OFFSET_CHAIN_SECTOR);
+ }
+ else
+ {
+ // Free the rest of the chain
+ u8 track_to_free = datablk->r8(OFFSET_CHAIN_TRACK);
+ u8 sector_to_free = datablk->r8(OFFSET_CHAIN_SECTOR);
+
+ while (track_to_free != CHAIN_END)
+ {
+ std::error_condition const err = free_sector(track_to_free, sector_to_free);
+ if (err)
+ return err;
+ datablk = read_sector(track_to_free, sector_to_free);
+ track_to_free = datablk->r8(OFFSET_CHAIN_TRACK);
+ sector_to_free = datablk->r8(OFFSET_CHAIN_SECTOR);
+ }
+ }
+ }
+ if (offset >= data_length)
+ {
+ datablk->w8(OFFSET_CHAIN_TRACK, CHAIN_END);
+ datablk->w8(OFFSET_CHAIN_SECTOR, bytes + 1);
+ }
+ }
+
+ // Write sector count and file type to directory entry
+ auto dirblk = read_sector(dir_track, dir_sector);
+ u8 file_type = determine_file_type(data);
+ if (file_type == FILE_TYPE_DEL)
+ {
+ // Free sector, update first file sector to 00
+ u8 file_track = dirblk->r8(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_FILE_FIRST_TRACK);
+ u8 file_sector = dirblk->r8(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_FILE_FIRST_SECTOR);
+ std::error_condition err = free_sector(file_track, file_sector);
+ if (err)
+ return err;
+ dirblk->w8(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_FILE_FIRST_TRACK, 0);
+ dirblk->w8(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_FILE_FIRST_SECTOR, 0);
+ sector_count = 0;
+ }
+ dirblk->w8(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_FILE_TYPE, file_type);
+ dirblk->w16l(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_SECTOR_COUNT, sector_count);
+
+ return std::error_condition();
+}
+
+
+u8 impl::determine_file_type(const std::vector<u8> &data) const
+{
+ // TODO: Determine/set the actual file type, defaulting to PRG for now.
+ const size_t data_length = data.size();
+ if (data_length == 0)
+ return FILE_TYPE_DEL;
+ return FILE_TYPE_PRG;
+}
+
+
+bool impl::is_valid_filename(const std::string &filename) const
+{
+ // We only support a subset of the character set supported by Commodore for filenames.
+ std::regex filename_regex("[A-Z0-9!\"#\\$%&'\\(\\)*+,-./:;<=>?]{1,16}");
+ return std::regex_match(filename, filename_regex);
+}
+
+
+std::pair<std::error_condition, u8> impl::claim_track_sector(u8 track) const
+{
+ if (track == 0 || track > m_max_track)
+ return std::make_pair(error::invalid_block, 0);
+
+ u8 map_index;
+ for (map_index = 0; map_index < TRACK_VARIANTS && !(s_track_sector_map[map_index].first_track <= track && track <= s_track_sector_map[map_index].last_track) ; map_index++);
+ if (map_index >= TRACK_VARIANTS)
+ return std::make_pair(error::invalid_block, 0);
+
+ auto bamblk = read_sector(DIRECTORY_TRACK, BAM_SECTOR);
+ u8 free_count = bamblk->r8(4 * track);
+ u32 free_bitmap = bamblk->r24l(4 * track + 1);
+
+ for (int s = 0; s < MAX_SECTORS; s++)
+ {
+ int sector = s_track_sector_map[map_index].sector[s];
+ if (sector >= 0 && free_count > 0 && util::BIT(free_bitmap, sector))
+ {
+ free_bitmap &= ~(1 << sector);
+ free_count--;
+ bamblk->w8(4 * track, free_count);
+ bamblk->w24l(4 * track + 1, free_bitmap);
+ // Write chain end marker in new sector
+ auto claimedlk = read_sector(track, sector);
+ claimedlk->w8(OFFSET_CHAIN_TRACK, CHAIN_END);
+ claimedlk->w8(OFFSET_CHAIN_SECTOR, 0xff);
+ return std::make_pair(std::error_condition(), sector);
+ }
+ }
+ return std::make_pair(error::no_space, 0);
+}
+
+
+std::tuple<std::error_condition, u8, u8> impl::claim_sector() const
+{
+ for (int track = 0; track < m_max_track - 1; track++)
+ {
+ auto const [err, sector] = claim_track_sector(s_data_track_order[track]);
+ if (!err)
+ return std::make_tuple(std::error_condition(), s_data_track_order[track], sector);
+ if (err != error::no_space)
+ return std::make_tuple(err, 0, 0);
+ }
+ return std::make_tuple(error::no_space, 0, 0);
+}
+
+
+std::error_condition impl::free_sector(u8 track, u8 sector) const
+{
+ if (track == 0 || track > m_max_track)
+ return error::invalid_block;
+
+ auto bamblk = read_sector(DIRECTORY_TRACK, BAM_SECTOR);
+ u8 free_count = bamblk->r8(4 * track);
+ u32 free_bitmap = bamblk->r24l(4 * track + 1);
+ free_bitmap |= (1 << sector);
+ free_count++;
+ bamblk->w8(4 * track, free_count);
+ bamblk->w24l(4 * track + 1, free_bitmap);
+ return std::error_condition();
}
@@ -300,7 +625,7 @@ std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string>
// impl::read_sector
//-------------------------------------------------
-fsblk_t::block_t impl::read_sector(int track, int sector) const
+fsblk_t::block_t::ptr impl::read_sector(int track, int sector) const
{
// CBM thinks in terms of tracks/sectors, but we have a block device abstraction
u32 block = 0;
@@ -320,13 +645,13 @@ fsblk_t::block_t impl::read_sector(int track, int sector) const
std::optional<impl::cbmdos_dirent> impl::dirent_from_path(const std::vector<std::string> &path) const
{
if (path.size() != 1)
- return { };
+ return std::nullopt;
std::string_view path_part = path[0];
std::optional<cbmdos_dirent> result;
- auto callback = [&result, path_part](const cbmdos_dirent &dirent)
+ auto const callback = [&result, path_part] (u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)
{
- bool found = strtrimright_cbm(dirent.m_file_name) == path_part;
+ bool const found = strtrimright_cbm(dirent.m_file_name) == path_part;
if (found)
result = dirent;
return found;
@@ -340,22 +665,38 @@ std::optional<impl::cbmdos_dirent> impl::dirent_from_path(const std::vector<std:
// impl::iterate_directory_entries
//-------------------------------------------------
-void impl::iterate_directory_entries(const std::function<bool(const cbmdos_dirent &dirent)> &callback) const
+void impl::iterate_directory_entries(const std::function<bool(u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)> &callback) const
{
- block_iterator iter(*this, 18, 1);
+ block_iterator iter(*this, DIRECTORY_TRACK, FIRST_DIRECTORY_SECTOR);
while (iter.next())
{
- for (const cbmdos_dirent &ent : iter.dirent_data())
+ auto entries = iter.dirent_data();
+
+ for (int file_index = 0; file_index < SECTOR_DIRECTORY_COUNT; file_index++)
{
- if (ent.m_file_type != 0x00)
+ if (entries[file_index].m_file_type != 0x00)
{
- if (callback(ent))
+ if (callback(iter.track(), iter.sector(), file_index, entries[file_index]))
return;
}
}
}
}
+void impl::iterate_all_directory_entries(const std::function<bool(u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)> &callback) const
+{
+ block_iterator iter(*this, DIRECTORY_TRACK, FIRST_DIRECTORY_SECTOR);
+ while (iter.next())
+ {
+ auto entries = iter.dirent_data();
+
+ for (int file_index = 0; file_index < SECTOR_DIRECTORY_COUNT; file_index++)
+ {
+ if (callback(iter.track(), iter.sector(), file_index, entries[file_index]))
+ return;
+ }
+ }
+}
//-------------------------------------------------
// impl::metadata_from_dirent
@@ -366,19 +707,19 @@ meta_data impl::metadata_from_dirent(const cbmdos_dirent &dirent) const
std::string file_type;
switch (dirent.m_file_type)
{
- case 0x80:
+ case FILE_TYPE_DEL:
file_type = "DEL";
break;
- case 0x81:
+ case FILE_TYPE_SEQ:
file_type = "SEQ";
break;
- case 0x82:
+ case FILE_TYPE_PRG:
file_type = "PRG";
break;
- case 0x83:
+ case FILE_TYPE_USR:
file_type = "USR";
break;
- case 0x84:
+ case FILE_TYPE_REL:
file_type = "REL";
break;
default:
@@ -409,6 +750,8 @@ impl::block_iterator::block_iterator(const impl &fs, u8 first_track, u8 first_se
: m_fs(fs)
, m_track(first_track)
, m_sector(first_sector)
+ , m_next_track(first_track)
+ , m_next_sector(first_sector)
{
}
@@ -420,19 +763,21 @@ impl::block_iterator::block_iterator(const impl &fs, u8 first_track, u8 first_se
bool impl::block_iterator::next()
{
bool result;
- if (m_track != 0x00)
+ m_track = m_next_track;
+ m_sector = m_next_sector;
+ if (m_track != CHAIN_END)
{
// check for the degenerate scenario where we have a cycle (this should not happen
// on a non-corrupt disk)
- auto visited_tuple = std::make_tuple(m_track, m_sector);
+ auto visited_tuple = std::make_tuple(m_next_track, m_next_sector);
if (m_visited_set.find(visited_tuple) != m_visited_set.end())
return false;
m_visited_set.insert(visited_tuple);
// with that out of the way, proceed
- m_block = m_fs.read_sector(m_track, m_sector);
- m_track = m_block.r8(0);
- m_sector = m_block.r8(1);
+ m_block = m_fs.read_sector(m_next_track, m_next_sector);
+ m_next_track = m_block->r8(OFFSET_CHAIN_TRACK);
+ m_next_sector = m_block->r8(OFFSET_CHAIN_SECTOR);
result = true;
}
else
@@ -450,7 +795,7 @@ bool impl::block_iterator::next()
const void *impl::block_iterator::data() const
{
- return m_block.rodata() + 2;
+ return m_block->rodata() + 2;
}
@@ -458,9 +803,9 @@ const void *impl::block_iterator::data() const
// impl::block_iterator::dirent_data
//-------------------------------------------------
-const std::array<impl::cbmdos_dirent, 4> &impl::block_iterator::dirent_data() const
+const std::array<impl::cbmdos_dirent, impl::SECTOR_DIRECTORY_COUNT> &impl::block_iterator::dirent_data() const
{
- return *reinterpret_cast<const std::array<impl::cbmdos_dirent, 4> *>(m_block.rodata());
+ return *reinterpret_cast<const std::array<impl::cbmdos_dirent, SECTOR_DIRECTORY_COUNT> *>(m_block->rodata());
}
@@ -470,7 +815,7 @@ const std::array<impl::cbmdos_dirent, 4> &impl::block_iterator::dirent_data() co
u8 impl::block_iterator::size() const
{
- return m_track != 0x00 ? 254 : m_sector - 1;
+ return (m_track != CHAIN_END) ? SECTOR_DATA_BYTES : (m_sector - 1);
}
} // anonymous namespace