Filesystem code cleanup
- Eliminate dependencies on emu.h, replacing most fatalerror calls and floptool's ersatz emu_fatalerror class with standard exception classes - Use range-based std::string constructors in some methods - Move filesystem metadata handling to a separate source file - Eliminate src/emu as an include path for libformats (necessitates kludge in ti99_dsk.cpp)
This commit is contained in:
parent
8a8b56bc24
commit
1214aac092
@ -21,7 +21,6 @@ project "formats"
|
|||||||
|
|
||||||
includedirs {
|
includedirs {
|
||||||
MAME_DIR .. "src/osd",
|
MAME_DIR .. "src/osd",
|
||||||
MAME_DIR .. "src/emu",
|
|
||||||
MAME_DIR .. "src/lib",
|
MAME_DIR .. "src/lib",
|
||||||
MAME_DIR .. "src/lib/util",
|
MAME_DIR .. "src/lib/util",
|
||||||
MAME_DIR .. "3rdparty",
|
MAME_DIR .. "3rdparty",
|
||||||
@ -80,6 +79,8 @@ project "formats"
|
|||||||
MAME_DIR .. "src/lib/formats/fsblk_vec.cpp",
|
MAME_DIR .. "src/lib/formats/fsblk_vec.cpp",
|
||||||
MAME_DIR .. "src/lib/formats/fs_unformatted.h",
|
MAME_DIR .. "src/lib/formats/fs_unformatted.h",
|
||||||
MAME_DIR .. "src/lib/formats/fs_unformatted.cpp",
|
MAME_DIR .. "src/lib/formats/fs_unformatted.cpp",
|
||||||
|
MAME_DIR .. "src/lib/formats/fsmeta.h",
|
||||||
|
MAME_DIR .. "src/lib/formats/fsmeta.cpp",
|
||||||
}
|
}
|
||||||
|
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
// Enumerate all the compiled-in formats
|
// Enumerate all the compiled-in formats
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
#include "has_formats.h" // Generated by genie
|
#include "has_formats.h" // Generated by genie
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
// Management of Oric Jasmin floppy images
|
// Management of Oric Jasmin floppy images
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "fs_oric_jasmin.h"
|
#include "fs_oric_jasmin.h"
|
||||||
#include "oric_dsk.h"
|
#include "oric_dsk.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
const fs_oric_jasmin FS_ORIC_JASMIN;
|
const fs_oric_jasmin FS_ORIC_JASMIN;
|
||||||
|
|
||||||
// Floppy only, format is 41 tracks, 1/2 heads, 17 sectors.
|
// Floppy only, format is 41 tracks, 1/2 heads, 17 sectors.
|
||||||
@ -129,14 +130,14 @@ std::vector<fs_meta_description> fs_oric_jasmin::file_meta_description() const
|
|||||||
void fs_oric_jasmin::impl::format(const fs_meta_data &meta)
|
void fs_oric_jasmin::impl::format(const fs_meta_data &meta)
|
||||||
{
|
{
|
||||||
std::string volume_name = meta.get_string(fs_meta_name::name, "UNTITLED");
|
std::string volume_name = meta.get_string(fs_meta_name::name, "UNTITLED");
|
||||||
u32 blocks = m_blockdev.block_count();
|
uint32_t blocks = m_blockdev.block_count();
|
||||||
|
|
||||||
m_blockdev.fill(0x6c);
|
m_blockdev.fill(0x6c);
|
||||||
|
|
||||||
u32 bblk = 20*17;
|
uint32_t bblk = 20*17;
|
||||||
auto fmap = m_blockdev.get(bblk);
|
auto fmap = m_blockdev.get(bblk);
|
||||||
u32 off = 0;
|
uint32_t off = 0;
|
||||||
for(u32 blk = 0; blk != blocks; blk += 17) {
|
for(uint32_t blk = 0; blk != blocks; blk += 17) {
|
||||||
if(blk == bblk)
|
if(blk == bblk)
|
||||||
fmap.w24l(off, 0x07fff);
|
fmap.w24l(off, 0x07fff);
|
||||||
else
|
else
|
||||||
@ -144,7 +145,7 @@ void fs_oric_jasmin::impl::format(const fs_meta_data &meta)
|
|||||||
off += 3;
|
off += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(u32 blk = blocks; blk != 17*42*2; blk += 17) {
|
for(uint32_t blk = blocks; blk != 17*42*2; blk += 17) {
|
||||||
fmap.w24l(off, 0x800000);
|
fmap.w24l(off, 0x800000);
|
||||||
off += 3;
|
off += 3;
|
||||||
}
|
}
|
||||||
@ -164,10 +165,10 @@ fs_oric_jasmin::impl::impl(fsblk_t &blockdev) : filesystem_t(blockdev, 256), m_r
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs_oric_jasmin::impl::ref_valid(u16 ref)
|
bool fs_oric_jasmin::impl::ref_valid(uint16_t ref)
|
||||||
{
|
{
|
||||||
u8 track = ref >> 8;
|
uint8_t track = ref >> 8;
|
||||||
u8 sector = ref & 0xff;
|
uint8_t sector = ref & 0xff;
|
||||||
if(sector < 1 || sector > 17)
|
if(sector < 1 || sector > 17)
|
||||||
return false;
|
return false;
|
||||||
if(track >= m_blockdev.block_count()/17)
|
if(track >= m_blockdev.block_count()/17)
|
||||||
@ -175,21 +176,21 @@ bool fs_oric_jasmin::impl::ref_valid(u16 ref)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 fs_oric_jasmin::impl::cs_to_block(u16 ref)
|
uint32_t fs_oric_jasmin::impl::cs_to_block(uint16_t ref)
|
||||||
{
|
{
|
||||||
u8 track = ref >> 8;
|
uint8_t track = ref >> 8;
|
||||||
u8 sector = ref & 0xff;
|
uint8_t sector = ref & 0xff;
|
||||||
return track * 17 + sector - 1;
|
return track * 17 + sector - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 fs_oric_jasmin::impl::block_to_cs(u32 block)
|
uint16_t fs_oric_jasmin::impl::block_to_cs(uint32_t block)
|
||||||
{
|
{
|
||||||
u8 track = block / 17;
|
uint8_t track = block / 17;
|
||||||
u8 sector = (block % 17) + 1;
|
uint8_t sector = (block % 17) + 1;
|
||||||
return (track << 8) | sector;
|
return (track << 8) | sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fs_oric_jasmin::impl::read_file_name(const u8 *p)
|
std::string fs_oric_jasmin::impl::read_file_name(const uint8_t *p)
|
||||||
{
|
{
|
||||||
int main_len;
|
int main_len;
|
||||||
for(main_len = 8; main_len > 0; main_len--)
|
for(main_len = 8; main_len > 0; main_len--)
|
||||||
@ -237,9 +238,9 @@ std::vector<fs_dir_entry> fs_oric_jasmin::impl::root_dir::contents()
|
|||||||
auto bdir = m_fs.m_blockdev.get(20*17+1);
|
auto bdir = m_fs.m_blockdev.get(20*17+1);
|
||||||
uint64_t id = 0;
|
uint64_t id = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
for(u32 i = 0; i != 14; i ++) {
|
for(uint32_t i = 0; i != 14; i ++) {
|
||||||
u32 off = 4 + i*18;
|
uint32_t off = 4 + i*18;
|
||||||
u16 ref = bdir.r16b(off);
|
uint16_t ref = bdir.r16b(off);
|
||||||
std::string fname = read_file_name(bdir.rodata()+off+3);
|
std::string fname = read_file_name(bdir.rodata()+off+3);
|
||||||
bool system = ref == 0 && id == 0 && bdir.r32b(off+0xb) == 0x2e535953;
|
bool system = ref == 0 && id == 0 && bdir.r32b(off+0xb) == 0x2e535953;
|
||||||
if(system)
|
if(system)
|
||||||
@ -250,7 +251,7 @@ std::vector<fs_dir_entry> fs_oric_jasmin::impl::root_dir::contents()
|
|||||||
|
|
||||||
id++;
|
id++;
|
||||||
}
|
}
|
||||||
u16 ref = bdir.r16b(2);
|
uint16_t ref = bdir.r16b(2);
|
||||||
if(!ref || !m_fs.ref_valid(ref))
|
if(!ref || !m_fs.ref_valid(ref))
|
||||||
break;
|
break;
|
||||||
bdir = m_fs.m_blockdev.get(cs_to_block(ref));
|
bdir = m_fs.m_blockdev.get(cs_to_block(ref));
|
||||||
@ -258,34 +259,34 @@ std::vector<fs_dir_entry> fs_oric_jasmin::impl::root_dir::contents()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<fsblk_t::block_t, u32> fs_oric_jasmin::impl::root_dir::get_dir_block(uint64_t key)
|
std::pair<fsblk_t::block_t, uint32_t> fs_oric_jasmin::impl::root_dir::get_dir_block(uint64_t key)
|
||||||
{
|
{
|
||||||
auto bdir = m_fs.m_blockdev.get(20*17+1);
|
auto bdir = m_fs.m_blockdev.get(20*17+1);
|
||||||
while(key >= 14) {
|
while(key >= 14) {
|
||||||
u16 ref = bdir.r16b(2);
|
uint16_t ref = bdir.r16b(2);
|
||||||
if(!ref || !m_fs.ref_valid(ref))
|
if(!ref || !m_fs.ref_valid(ref))
|
||||||
fatalerror("Incorrect file key\n");
|
throw std::invalid_argument("Incorrect file key");
|
||||||
bdir = m_fs.m_blockdev.get(cs_to_block(ref));
|
bdir = m_fs.m_blockdev.get(cs_to_block(ref));
|
||||||
key -= 14;
|
key -= 14;
|
||||||
}
|
}
|
||||||
return std::pair<fsblk_t::block_t, u32>(bdir, 4 + key * 18);
|
return std::pair<fsblk_t::block_t, uint32_t>(bdir, 4 + key * 18);
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystem_t::file_t fs_oric_jasmin::impl::root_dir::file_get(uint64_t key)
|
filesystem_t::file_t fs_oric_jasmin::impl::root_dir::file_get(uint64_t key)
|
||||||
{
|
{
|
||||||
uint64_t rkey = key;
|
uint64_t rkey = key;
|
||||||
auto [bdir, off] = get_dir_block(rkey);
|
auto [bdir, off] = get_dir_block(rkey);
|
||||||
u16 ref = bdir.r16b(off);
|
uint16_t ref = bdir.r16b(off);
|
||||||
bool system = ref == 0 && key == 0 && bdir.r32b(off+0xb) == 0x2e535953;
|
bool system = ref == 0 && key == 0 && bdir.r32b(off+0xb) == 0x2e535953;
|
||||||
if(system)
|
if(system)
|
||||||
return file_t(new system_file(m_fs, this, bdir.rodata() + off, key));
|
return file_t(new system_file(m_fs, this, bdir.rodata() + off, key));
|
||||||
|
|
||||||
if(!m_fs.ref_valid(ref))
|
if(!m_fs.ref_valid(ref))
|
||||||
fatalerror("Key to deleted/non-existent file\n");
|
throw std::invalid_argument("Key to deleted/non-existent file");
|
||||||
return file_t(new file(m_fs, this, bdir.rodata() + off, key));
|
return file_t(new file(m_fs, this, bdir.rodata() + off, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_oric_jasmin::impl::root_dir::update_file(u16 key, const u8 *entry)
|
void fs_oric_jasmin::impl::root_dir::update_file(uint16_t key, const uint8_t *entry)
|
||||||
{
|
{
|
||||||
uint64_t rkey = key;
|
uint64_t rkey = key;
|
||||||
auto [bdir, off] = get_dir_block(rkey);
|
auto [bdir, off] = get_dir_block(rkey);
|
||||||
@ -294,7 +295,7 @@ void fs_oric_jasmin::impl::root_dir::update_file(u16 key, const u8 *entry)
|
|||||||
|
|
||||||
filesystem_t::dir_t fs_oric_jasmin::impl::root_dir::dir_get(uint64_t key)
|
filesystem_t::dir_t fs_oric_jasmin::impl::root_dir::dir_get(uint64_t key)
|
||||||
{
|
{
|
||||||
fatalerror("Directories not supported\n");
|
throw std::logic_error("Directories not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fs_oric_jasmin::impl::file_name_prepare(std::string fname)
|
std::string fs_oric_jasmin::impl::file_name_prepare(std::string fname)
|
||||||
@ -317,7 +318,7 @@ std::string fs_oric_jasmin::impl::file_name_prepare(std::string fname)
|
|||||||
return nname;
|
return nname;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_oric_jasmin::impl::file::file(impl &fs, root_dir *dir, const u8 *entry, u16 key) : m_fs(fs), m_dir(dir), m_key(key)
|
fs_oric_jasmin::impl::file::file(impl &fs, root_dir *dir, const uint8_t *entry, uint16_t key) : m_fs(fs), m_dir(dir), m_key(key)
|
||||||
{
|
{
|
||||||
memcpy(m_entry, entry, 18);
|
memcpy(m_entry, entry, 18);
|
||||||
}
|
}
|
||||||
@ -335,7 +336,7 @@ fs_meta_data fs_oric_jasmin::impl::file::metadata()
|
|||||||
res.set(fs_meta_name::sequential, m_entry[0xf] == 'S');
|
res.set(fs_meta_name::sequential, m_entry[0xf] == 'S');
|
||||||
res.set(fs_meta_name::size_in_blocks, r16l(m_entry + 0x10));
|
res.set(fs_meta_name::size_in_blocks, r16l(m_entry + 0x10));
|
||||||
|
|
||||||
u16 ref = r16b(m_entry);
|
uint16_t ref = r16b(m_entry);
|
||||||
auto dblk = m_fs.m_blockdev.get(cs_to_block(ref));
|
auto dblk = m_fs.m_blockdev.get(cs_to_block(ref));
|
||||||
res.set(fs_meta_name::loading_address, dblk.r16l(2));
|
res.set(fs_meta_name::loading_address, dblk.r16l(2));
|
||||||
res.set(fs_meta_name::length, dblk.r16l(4));
|
res.set(fs_meta_name::length, dblk.r16l(4));
|
||||||
@ -343,19 +344,19 @@ fs_meta_data fs_oric_jasmin::impl::file::metadata()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> fs_oric_jasmin::impl::file::read_all()
|
std::vector<uint8_t> fs_oric_jasmin::impl::file::read_all()
|
||||||
{
|
{
|
||||||
std::vector<u8> data;
|
std::vector<uint8_t> data;
|
||||||
u16 ref = r16b(m_entry);
|
uint16_t ref = r16b(m_entry);
|
||||||
auto iblk = m_fs.m_blockdev.get(cs_to_block(ref));
|
auto iblk = m_fs.m_blockdev.get(cs_to_block(ref));
|
||||||
u32 length = iblk.r16l(4);
|
uint32_t length = iblk.r16l(4);
|
||||||
while(m_fs.ref_valid(ref)) {
|
while(m_fs.ref_valid(ref)) {
|
||||||
for(u32 pos = 6; pos != 256 && data.size() < length; pos += 2) {
|
for(uint32_t pos = 6; pos != 256 && data.size() < length; pos += 2) {
|
||||||
u16 dref = iblk.r16b(pos);
|
uint16_t dref = iblk.r16b(pos);
|
||||||
if(!m_fs.ref_valid(dref))
|
if(!m_fs.ref_valid(dref))
|
||||||
goto done;
|
goto done;
|
||||||
auto dblk = m_fs.m_blockdev.get(cs_to_block(dref));
|
auto dblk = m_fs.m_blockdev.get(cs_to_block(dref));
|
||||||
u32 dpos = data.size();
|
uint32_t dpos = data.size();
|
||||||
data.resize(dpos + 256);
|
data.resize(dpos + 256);
|
||||||
memcpy(data.data() + dpos, dblk.rodata(), 256);
|
memcpy(data.data() + dpos, dblk.rodata(), 256);
|
||||||
if(data.size() >= length)
|
if(data.size() >= length)
|
||||||
@ -371,7 +372,7 @@ std::vector<u8> fs_oric_jasmin::impl::file::read_all()
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_oric_jasmin::impl::system_file::system_file(impl &fs, root_dir *dir, const u8 *entry, u16 key) : m_fs(fs), m_dir(dir), m_key(key)
|
fs_oric_jasmin::impl::system_file::system_file(impl &fs, root_dir *dir, const uint8_t *entry, uint16_t key) : m_fs(fs), m_dir(dir), m_key(key)
|
||||||
{
|
{
|
||||||
memcpy(m_entry, entry, 18);
|
memcpy(m_entry, entry, 18);
|
||||||
}
|
}
|
||||||
@ -393,10 +394,10 @@ fs_meta_data fs_oric_jasmin::impl::system_file::metadata()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> fs_oric_jasmin::impl::system_file::read_all()
|
std::vector<uint8_t> fs_oric_jasmin::impl::system_file::read_all()
|
||||||
{
|
{
|
||||||
std::vector<u8> data(0x3e00);
|
std::vector<uint8_t> data(0x3e00);
|
||||||
for(u32 i = 0; i != 62; i++) {
|
for(uint32_t i = 0; i != 62; i++) {
|
||||||
auto dblk = m_fs.m_blockdev.get(i);
|
auto dblk = m_fs.m_blockdev.get(i);
|
||||||
memcpy(data.data() + 256 * i, dblk.rodata(), 256);
|
memcpy(data.data() + 256 * i, dblk.rodata(), 256);
|
||||||
}
|
}
|
||||||
@ -406,20 +407,20 @@ std::vector<u8> fs_oric_jasmin::impl::system_file::read_all()
|
|||||||
fs_oric_jasmin::impl::file_t fs_oric_jasmin::impl::root_dir::file_create(const fs_meta_data &info)
|
fs_oric_jasmin::impl::file_t fs_oric_jasmin::impl::root_dir::file_create(const fs_meta_data &info)
|
||||||
{
|
{
|
||||||
// One block of sector list, one block of data
|
// One block of sector list, one block of data
|
||||||
u32 nb = 2;
|
uint32_t nb = 2;
|
||||||
|
|
||||||
// Find the key for the next entry, increase nb if needed
|
// Find the key for the next entry, increase nb if needed
|
||||||
auto bdir = m_fs.m_blockdev.get(20*17+1);
|
auto bdir = m_fs.m_blockdev.get(20*17+1);
|
||||||
uint64_t id = 0;
|
uint64_t id = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
for(u32 i = 0; i != 14; i ++) {
|
for(uint32_t i = 0; i != 14; i ++) {
|
||||||
u32 off = 4 + i*18;
|
uint32_t off = 4 + i*18;
|
||||||
u16 ref = bdir.r16b(off);
|
uint16_t ref = bdir.r16b(off);
|
||||||
if(!m_fs.ref_valid(ref))
|
if(!m_fs.ref_valid(ref))
|
||||||
goto found;
|
goto found;
|
||||||
id++;
|
id++;
|
||||||
}
|
}
|
||||||
u16 ref = bdir.r16b(2);
|
uint16_t ref = bdir.r16b(2);
|
||||||
if(!ref || !m_fs.ref_valid(ref)) {
|
if(!ref || !m_fs.ref_valid(ref)) {
|
||||||
nb ++;
|
nb ++;
|
||||||
break;
|
break;
|
||||||
@ -445,7 +446,7 @@ fs_oric_jasmin::impl::file_t fs_oric_jasmin::impl::root_dir::file_create(const f
|
|||||||
bdir.w16l(2, 0xff00); // No next directory sector
|
bdir.w16l(2, 0xff00); // No next directory sector
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 off = 4 + (id % 14) * 18;
|
uint32_t off = 4 + (id % 14) * 18;
|
||||||
bdir.w16b(off+0x00, block[0]); // First (and only) sector in the sector list
|
bdir.w16b(off+0x00, block[0]); // First (and only) sector in the sector list
|
||||||
bdir.w8 (off+0x02, info.get_flag(fs_meta_name::locked, false) ? 'L' : 'U');
|
bdir.w8 (off+0x02, info.get_flag(fs_meta_name::locked, false) ? 'L' : 'U');
|
||||||
bdir.wstr(off+0x03, file_name_prepare(info.get_string(fs_meta_name::name, "")));
|
bdir.wstr(off+0x03, file_name_prepare(info.get_string(fs_meta_name::name, "")));
|
||||||
@ -461,11 +462,11 @@ void fs_oric_jasmin::impl::root_dir::file_delete(uint64_t key)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_oric_jasmin::impl::file::replace(const std::vector<u8> &data)
|
void fs_oric_jasmin::impl::file::replace(const std::vector<uint8_t> &data)
|
||||||
{
|
{
|
||||||
u32 cur_ns = r16l(m_entry + 0x10);
|
uint32_t cur_ns = r16l(m_entry + 0x10);
|
||||||
// Data sectors first
|
// Data sectors first
|
||||||
u32 need_ns = (data.size() + 255) / 256;
|
uint32_t need_ns = (data.size() + 255) / 256;
|
||||||
if(need_ns == 0)
|
if(need_ns == 0)
|
||||||
need_ns = 1;
|
need_ns = 1;
|
||||||
// Add the sector list sectors, 125 entries/sector
|
// Add the sector list sectors, 125 entries/sector
|
||||||
@ -475,22 +476,22 @@ void fs_oric_jasmin::impl::file::replace(const std::vector<u8> &data)
|
|||||||
if(cur_ns < need_ns && m_fs.free_block_count() < need_ns - cur_ns)
|
if(cur_ns < need_ns && m_fs.free_block_count() < need_ns - cur_ns)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u16 load_address = 0;
|
uint16_t load_address = 0;
|
||||||
std::vector<u16> tofree;
|
std::vector<uint16_t> tofree;
|
||||||
u16 iref = r16b(m_entry);
|
uint16_t iref = r16b(m_entry);
|
||||||
for(u32 i=0; i < cur_ns; i += 125+1) {
|
for(uint32_t i=0; i < cur_ns; i += 125+1) {
|
||||||
auto iblk = m_fs.m_blockdev.get(cs_to_block(iref));
|
auto iblk = m_fs.m_blockdev.get(cs_to_block(iref));
|
||||||
if(!i)
|
if(!i)
|
||||||
load_address = iblk.r16l(2);
|
load_address = iblk.r16l(2);
|
||||||
tofree.push_back(iref);
|
tofree.push_back(iref);
|
||||||
for(u32 j=0; j != 125 && i+j+1 != cur_ns; j++)
|
for(uint32_t j=0; j != 125 && i+j+1 != cur_ns; j++)
|
||||||
tofree.push_back(iblk.r16b(6+2*j));
|
tofree.push_back(iblk.r16b(6+2*j));
|
||||||
iref = iblk.r16b(2);
|
iref = iblk.r16b(2);
|
||||||
}
|
}
|
||||||
m_fs.free_blocks(tofree);
|
m_fs.free_blocks(tofree);
|
||||||
|
|
||||||
std::vector<u16> blocks = m_fs.allocate_blocks(need_ns);
|
std::vector<uint16_t> blocks = m_fs.allocate_blocks(need_ns);
|
||||||
for(u32 i=0; i < need_ns; i += 125+1) {
|
for(uint32_t i=0; i < need_ns; i += 125+1) {
|
||||||
auto iblk = m_fs.m_blockdev.get(cs_to_block(blocks[i]));
|
auto iblk = m_fs.m_blockdev.get(cs_to_block(blocks[i]));
|
||||||
iblk.fill(0xff);
|
iblk.fill(0xff);
|
||||||
if(!i) {
|
if(!i) {
|
||||||
@ -502,9 +503,9 @@ void fs_oric_jasmin::impl::file::replace(const std::vector<u8> &data)
|
|||||||
else
|
else
|
||||||
iblk.w16b(0, 0xff00);
|
iblk.w16b(0, 0xff00);
|
||||||
|
|
||||||
for(u32 j=0; j != 125 && i+j+1 != need_ns; j++) {
|
for(uint32_t j=0; j != 125 && i+j+1 != need_ns; j++) {
|
||||||
u32 dpos = 256 * (j + i/126*125);
|
uint32_t dpos = 256 * (j + i/126*125);
|
||||||
u32 size = data.size() - dpos;
|
uint32_t size = data.size() - dpos;
|
||||||
iblk.w16b(6+j*2, blocks[i+j+1]);
|
iblk.w16b(6+j*2, blocks[i+j+1]);
|
||||||
auto dblk = m_fs.m_blockdev.get(cs_to_block(blocks[i+j+1]));
|
auto dblk = m_fs.m_blockdev.get(cs_to_block(blocks[i+j+1]));
|
||||||
if(size >= 256)
|
if(size >= 256)
|
||||||
@ -546,12 +547,12 @@ void fs_oric_jasmin::impl::file::metadata_change(const fs_meta_data &info)
|
|||||||
m_dir->update_file(m_key, m_entry);
|
m_dir->update_file(m_key, m_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_oric_jasmin::impl::system_file::replace(const std::vector<u8> &data)
|
void fs_oric_jasmin::impl::system_file::replace(const std::vector<uint8_t> &data)
|
||||||
{
|
{
|
||||||
if(data.size() != 0x3e00)
|
if(data.size() != 0x3e00)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for(u32 i=0; i != 0x3e; i++)
|
for(uint32_t i=0; i != 0x3e; i++)
|
||||||
m_fs.m_blockdev.get(i).copy(0, data.data() + i * 256, 256);
|
m_fs.m_blockdev.get(i).copy(0, data.data() + i * 256, 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,18 +569,18 @@ void fs_oric_jasmin::impl::system_file::metadata_change(const fs_meta_data &info
|
|||||||
m_dir->update_file(m_key, m_entry);
|
m_dir->update_file(m_key, m_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u16> fs_oric_jasmin::impl::allocate_blocks(u32 count)
|
std::vector<uint16_t> fs_oric_jasmin::impl::allocate_blocks(uint32_t count)
|
||||||
{
|
{
|
||||||
std::vector<u16> blocks;
|
std::vector<uint16_t> blocks;
|
||||||
if(free_block_count() < count)
|
if(free_block_count() < count)
|
||||||
return blocks;
|
return blocks;
|
||||||
|
|
||||||
auto fmap = m_blockdev.get(20*17);
|
auto fmap = m_blockdev.get(20*17);
|
||||||
u32 nf = 0;
|
uint32_t nf = 0;
|
||||||
for(u32 track = 0; track != 2*41 && nf != count; track++) {
|
for(uint32_t track = 0; track != 2*41 && nf != count; track++) {
|
||||||
u32 map = fmap.r24l(track*3);
|
uint32_t map = fmap.r24l(track*3);
|
||||||
if(map != 0x800000) {
|
if(map != 0x800000) {
|
||||||
for(u32 sect = 1; sect <= 17 && nf != count; sect++)
|
for(uint32_t sect = 1; sect <= 17 && nf != count; sect++)
|
||||||
if(map & (0x20000 >> sect)) {
|
if(map & (0x20000 >> sect)) {
|
||||||
blocks.push_back((track << 8) | sect);
|
blocks.push_back((track << 8) | sect);
|
||||||
map &= ~(0x20000 >> sect);
|
map &= ~(0x20000 >> sect);
|
||||||
@ -593,13 +594,13 @@ std::vector<u16> fs_oric_jasmin::impl::allocate_blocks(u32 count)
|
|||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_oric_jasmin::impl::free_blocks(const std::vector<u16> &blocks)
|
void fs_oric_jasmin::impl::free_blocks(const std::vector<uint16_t> &blocks)
|
||||||
{
|
{
|
||||||
auto fmap = m_blockdev.get(20*17);
|
auto fmap = m_blockdev.get(20*17);
|
||||||
for(u16 ref : blocks) {
|
for(uint16_t ref : blocks) {
|
||||||
u32 track = ref >> 8;
|
uint32_t track = ref >> 8;
|
||||||
u32 sect = ref & 0xff;
|
uint32_t sect = ref & 0xff;
|
||||||
u32 map = fmap.r24l(track*3);
|
uint32_t map = fmap.r24l(track*3);
|
||||||
if(map == 0x800000)
|
if(map == 0x800000)
|
||||||
map = 0;
|
map = 0;
|
||||||
map |= 0x20000 >> sect;
|
map |= 0x20000 >> sect;
|
||||||
@ -607,14 +608,14 @@ void fs_oric_jasmin::impl::free_blocks(const std::vector<u16> &blocks)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 fs_oric_jasmin::impl::free_block_count()
|
uint32_t fs_oric_jasmin::impl::free_block_count()
|
||||||
{
|
{
|
||||||
auto fmap = m_blockdev.get(20*17);
|
auto fmap = m_blockdev.get(20*17);
|
||||||
u32 nf = 0;
|
uint32_t nf = 0;
|
||||||
for(u32 track = 0; track != 2*41; track++) {
|
for(uint32_t track = 0; track != 2*41; track++) {
|
||||||
u32 map = fmap.r24l(track*3);
|
uint32_t map = fmap.r24l(track*3);
|
||||||
if(map != 0x800000) {
|
if(map != 0x800000) {
|
||||||
for(u32 sect = 1; sect <= 17; sect++)
|
for(uint32_t sect = 1; sect <= 17; sect++)
|
||||||
if(map & (0x20000 >> sect))
|
if(map & (0x20000 >> sect))
|
||||||
nf++;
|
nf++;
|
||||||
}
|
}
|
||||||
|
@ -29,50 +29,50 @@ public:
|
|||||||
virtual file_t file_create(const fs_meta_data &info) override;
|
virtual file_t file_create(const fs_meta_data &info) override;
|
||||||
virtual void file_delete(uint64_t key) override;
|
virtual void file_delete(uint64_t key) override;
|
||||||
|
|
||||||
void update_file(u16 key, const u8 *entry);
|
void update_file(uint16_t key, const uint8_t *entry);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
impl &m_fs;
|
impl &m_fs;
|
||||||
|
|
||||||
std::pair<fsblk_t::block_t, u32> get_dir_block(uint64_t key);
|
std::pair<fsblk_t::block_t, uint32_t> get_dir_block(uint64_t key);
|
||||||
};
|
};
|
||||||
|
|
||||||
class file : public ifile_t {
|
class file : public ifile_t {
|
||||||
public:
|
public:
|
||||||
file(impl &fs, root_dir *dir, const u8 *entry, u16 key);
|
file(impl &fs, root_dir *dir, const uint8_t *entry, uint16_t key);
|
||||||
virtual ~file() = default;
|
virtual ~file() = default;
|
||||||
|
|
||||||
virtual void drop_weak_references() override;
|
virtual void drop_weak_references() override;
|
||||||
|
|
||||||
virtual fs_meta_data metadata() override;
|
virtual fs_meta_data metadata() override;
|
||||||
virtual void metadata_change(const fs_meta_data &info) override;
|
virtual void metadata_change(const fs_meta_data &info) override;
|
||||||
virtual std::vector<u8> read_all() override;
|
virtual std::vector<uint8_t> read_all() override;
|
||||||
virtual void replace(const std::vector<u8> &data) override;
|
virtual void replace(const std::vector<uint8_t> &data) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
impl &m_fs;
|
impl &m_fs;
|
||||||
root_dir *m_dir;
|
root_dir *m_dir;
|
||||||
u16 m_key;
|
uint16_t m_key;
|
||||||
u8 m_entry[18];
|
uint8_t m_entry[18];
|
||||||
};
|
};
|
||||||
|
|
||||||
class system_file : public ifile_t {
|
class system_file : public ifile_t {
|
||||||
public:
|
public:
|
||||||
system_file(impl &fs, root_dir *dir, const u8 *entry, u16 key);
|
system_file(impl &fs, root_dir *dir, const uint8_t *entry, uint16_t key);
|
||||||
virtual ~system_file() = default;
|
virtual ~system_file() = default;
|
||||||
|
|
||||||
virtual void drop_weak_references() override;
|
virtual void drop_weak_references() override;
|
||||||
|
|
||||||
virtual fs_meta_data metadata() override;
|
virtual fs_meta_data metadata() override;
|
||||||
virtual void metadata_change(const fs_meta_data &info) override;
|
virtual void metadata_change(const fs_meta_data &info) override;
|
||||||
virtual std::vector<u8> read_all() override;
|
virtual std::vector<uint8_t> read_all() override;
|
||||||
virtual void replace(const std::vector<u8> &data) override;
|
virtual void replace(const std::vector<uint8_t> &data) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
impl &m_fs;
|
impl &m_fs;
|
||||||
root_dir *m_dir;
|
root_dir *m_dir;
|
||||||
u16 m_key;
|
uint16_t m_key;
|
||||||
u8 m_entry[18];
|
uint8_t m_entry[18];
|
||||||
};
|
};
|
||||||
|
|
||||||
impl(fsblk_t &blockdev);
|
impl(fsblk_t &blockdev);
|
||||||
@ -83,16 +83,16 @@ public:
|
|||||||
virtual void metadata_change(const fs_meta_data &info) override;
|
virtual void metadata_change(const fs_meta_data &info) override;
|
||||||
virtual dir_t root() override;
|
virtual dir_t root() override;
|
||||||
|
|
||||||
static u32 cs_to_block(u16 ref);
|
static uint32_t cs_to_block(uint16_t ref);
|
||||||
static u16 block_to_cs(u32 block);
|
static uint16_t block_to_cs(uint32_t block);
|
||||||
|
|
||||||
bool ref_valid(u16 ref);
|
bool ref_valid(uint16_t ref);
|
||||||
static std::string read_file_name(const u8 *p);
|
static std::string read_file_name(const uint8_t *p);
|
||||||
void drop_root_ref();
|
void drop_root_ref();
|
||||||
|
|
||||||
std::vector<u16> allocate_blocks(u32 count);
|
std::vector<uint16_t> allocate_blocks(uint32_t count);
|
||||||
void free_blocks(const std::vector<u16> &blocks);
|
void free_blocks(const std::vector<uint16_t> &blocks);
|
||||||
u32 free_block_count();
|
uint32_t free_block_count();
|
||||||
|
|
||||||
static std::string file_name_prepare(std::string name);
|
static std::string file_name_prepare(std::string name);
|
||||||
|
|
||||||
|
@ -3,10 +3,13 @@
|
|||||||
|
|
||||||
// Creation of Apple ProDOS floppy images
|
// Creation of Apple ProDOS floppy images
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "fs_prodos.h"
|
#include "fs_prodos.h"
|
||||||
#include "ap_dsk35.h"
|
#include "ap_dsk35.h"
|
||||||
|
|
||||||
|
#include "strformat.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
const fs_prodos FS_PRODOS;
|
const fs_prodos FS_PRODOS;
|
||||||
|
|
||||||
@ -20,7 +23,7 @@ const char *fs_prodos::description() const
|
|||||||
return "Apple ProDOS";
|
return "Apple ProDOS";
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8 fs_prodos::impl::boot[512] = {
|
const uint8_t fs_prodos::impl::boot[512] = {
|
||||||
0x01, 0x38, 0xb0, 0x03, 0x4c, 0x1c, 0x09, 0x78, 0x86, 0x43, 0xc9, 0x03, 0x08, 0x8a, 0x29, 0x70,
|
0x01, 0x38, 0xb0, 0x03, 0x4c, 0x1c, 0x09, 0x78, 0x86, 0x43, 0xc9, 0x03, 0x08, 0x8a, 0x29, 0x70,
|
||||||
0x4a, 0x4a, 0x4a, 0x4a, 0x09, 0xc0, 0x85, 0x49, 0xa0, 0xff, 0x84, 0x48, 0x28, 0xc8, 0xb1, 0x48,
|
0x4a, 0x4a, 0x4a, 0x4a, 0x09, 0xc0, 0x85, 0x49, 0xa0, 0xff, 0x84, 0x48, 0x28, 0xc8, 0xb1, 0x48,
|
||||||
0xd0, 0x3a, 0xb0, 0x0e, 0xa9, 0x03, 0x8d, 0x00, 0x08, 0xe6, 0x3d, 0xa5, 0x49, 0x48, 0xa9, 0x5b,
|
0xd0, 0x3a, 0xb0, 0x0e, 0xa9, 0x03, 0x8d, 0x00, 0x08, 0xe6, 0x3d, 0xa5, 0x49, 0x48, 0xa9, 0x5b,
|
||||||
@ -137,7 +140,7 @@ std::vector<fs_meta_description> fs_prodos::directory_meta_description() const
|
|||||||
void fs_prodos::impl::format(const fs_meta_data &meta)
|
void fs_prodos::impl::format(const fs_meta_data &meta)
|
||||||
{
|
{
|
||||||
std::string volume_name = meta.get_string(fs_meta_name::name, "UNTITLED");
|
std::string volume_name = meta.get_string(fs_meta_name::name, "UNTITLED");
|
||||||
u32 blocks = m_blockdev.block_count();
|
uint32_t blocks = m_blockdev.block_count();
|
||||||
|
|
||||||
// Maximum usable partition size = 32M - 512 bytes (65535 blocks)
|
// Maximum usable partition size = 32M - 512 bytes (65535 blocks)
|
||||||
if(blocks >= 0x10000)
|
if(blocks >= 0x10000)
|
||||||
@ -174,20 +177,20 @@ void fs_prodos::impl::format(const fs_meta_data &meta)
|
|||||||
kblk4.w16l(0x00, 0x0004); // Backwards block pointer of the fourth volume block
|
kblk4.w16l(0x00, 0x0004); // Backwards block pointer of the fourth volume block
|
||||||
kblk4.w16l(0x02, 0x0000); // Forwards block pointer of the fourth volume block (null)
|
kblk4.w16l(0x02, 0x0000); // Forwards block pointer of the fourth volume block (null)
|
||||||
|
|
||||||
u32 fmap_block_count = (blocks + 4095) / 4096;
|
uint32_t fmap_block_count = (blocks + 4095) / 4096;
|
||||||
u32 first_free_block = 6 + fmap_block_count;
|
uint32_t first_free_block = 6 + fmap_block_count;
|
||||||
|
|
||||||
// Mark blocks from first_free_block to blocks-1 (the last one) as free
|
// Mark blocks from first_free_block to blocks-1 (the last one) as free
|
||||||
for(u32 i = 0; i != fmap_block_count; i++) {
|
for(uint32_t i = 0; i != fmap_block_count; i++) {
|
||||||
auto fmap = m_blockdev.get(6 + i);
|
auto fmap = m_blockdev.get(6 + i);
|
||||||
u8 *fdata = fmap.data();
|
uint8_t *fdata = fmap.data();
|
||||||
u32 start = i ? 0 : first_free_block;
|
uint32_t start = i ? 0 : first_free_block;
|
||||||
u32 end = i != fmap_block_count - 1 ? 4095 : (blocks - 1) & 4095;
|
uint32_t end = i != fmap_block_count - 1 ? 4095 : (blocks - 1) & 4095;
|
||||||
end += 1;
|
end += 1;
|
||||||
u32 sb = start >> 3;
|
uint32_t sb = start >> 3;
|
||||||
u32 si = start & 7;
|
uint32_t si = start & 7;
|
||||||
u32 eb = end >> 3;
|
uint32_t eb = end >> 3;
|
||||||
u32 ei = end & 7;
|
uint32_t ei = end & 7;
|
||||||
if(sb == eb)
|
if(sb == eb)
|
||||||
fdata[sb] = (0xff >> si) & ~(0xff >> ei);
|
fdata[sb] = (0xff >> si) & ~(0xff >> ei);
|
||||||
else {
|
else {
|
||||||
@ -204,7 +207,7 @@ fs_prodos::impl::impl(fsblk_t &blockdev) : filesystem_t(blockdev, 512), m_root(t
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
util::arbitrary_datetime fs_prodos::impl::prodos_to_dt(u32 date)
|
util::arbitrary_datetime fs_prodos::impl::prodos_to_dt(uint32_t date)
|
||||||
{
|
{
|
||||||
util::arbitrary_datetime dt;
|
util::arbitrary_datetime dt;
|
||||||
dt.second = 0;
|
dt.second = 0;
|
||||||
@ -260,13 +263,13 @@ std::vector<fs_dir_entry> fs_prodos::impl::root_dir::contents()
|
|||||||
{
|
{
|
||||||
std::vector<fs_dir_entry> res;
|
std::vector<fs_dir_entry> res;
|
||||||
|
|
||||||
u16 block = m_base_block;
|
uint16_t block = m_base_block;
|
||||||
u32 off = 39 + 4;
|
uint32_t off = 39 + 4;
|
||||||
u32 id = 1;
|
uint32_t id = 1;
|
||||||
do {
|
do {
|
||||||
auto blk = m_fs.m_blockdev.get(block);
|
auto blk = m_fs.m_blockdev.get(block);
|
||||||
while(off < 511) {
|
while(off < 511) {
|
||||||
u8 type = blk.r8(off);
|
uint8_t type = blk.r8(off);
|
||||||
auto name = blk.rstr(off+1, type & 0xf);
|
auto name = blk.rstr(off+1, type & 0xf);
|
||||||
type >>= 4;
|
type >>= 4;
|
||||||
if(type == 0xd)
|
if(type == 0xd)
|
||||||
@ -285,13 +288,13 @@ std::vector<fs_dir_entry> fs_prodos::impl::root_dir::contents()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::pair<fsblk_t::block_t, const u8 *> fs_prodos::impl::root_dir::get_entry_ro(uint64_t key)
|
std::pair<fsblk_t::block_t, const uint8_t *> fs_prodos::impl::root_dir::get_entry_ro(uint64_t key)
|
||||||
{
|
{
|
||||||
std::pair<fsblk_t::block_t, const u8 *> res;
|
std::pair<fsblk_t::block_t, const uint8_t *> res;
|
||||||
res.first = m_fs.m_blockdev.get(m_base_block);
|
res.first = m_fs.m_blockdev.get(m_base_block);
|
||||||
while(key >= 13) {
|
while(key >= 13) {
|
||||||
key -= 13;
|
key -= 13;
|
||||||
u16 block = res.first.r16l(2);
|
uint16_t block = res.first.r16l(2);
|
||||||
if(!block || block >= m_fs.m_blockdev.block_count()) {
|
if(!block || block >= m_fs.m_blockdev.block_count()) {
|
||||||
res.first = nullptr;
|
res.first = nullptr;
|
||||||
res.second = nullptr;
|
res.second = nullptr;
|
||||||
@ -303,13 +306,13 @@ std::pair<fsblk_t::block_t, const u8 *> fs_prodos::impl::root_dir::get_entry_ro(
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<fsblk_t::block_t, u8 *> fs_prodos::impl::root_dir::get_entry(uint64_t key)
|
std::pair<fsblk_t::block_t, uint8_t *> fs_prodos::impl::root_dir::get_entry(uint64_t key)
|
||||||
{
|
{
|
||||||
std::pair<fsblk_t::block_t, u8 *> res;
|
std::pair<fsblk_t::block_t, uint8_t *> res;
|
||||||
res.first = m_fs.m_blockdev.get(m_base_block);
|
res.first = m_fs.m_blockdev.get(m_base_block);
|
||||||
while(key > 13) {
|
while(key > 13) {
|
||||||
key -= 13;
|
key -= 13;
|
||||||
u16 block = res.first.r16l(2);
|
uint16_t block = res.first.r16l(2);
|
||||||
if(!block || block >= m_fs.m_blockdev.block_count()) {
|
if(!block || block >= m_fs.m_blockdev.block_count()) {
|
||||||
res.first = nullptr;
|
res.first = nullptr;
|
||||||
res.second = nullptr;
|
res.second = nullptr;
|
||||||
@ -325,10 +328,10 @@ filesystem_t::file_t fs_prodos::impl::root_dir::file_get(uint64_t key)
|
|||||||
{
|
{
|
||||||
auto [blk, entry] = get_entry_ro(key);
|
auto [blk, entry] = get_entry_ro(key);
|
||||||
if(!blk)
|
if(!blk)
|
||||||
fatalerror("Out-of-range key on file_get\n");
|
throw std::out_of_range("Out-of-range key on file_get");
|
||||||
u8 type = entry[0] >> 4;
|
uint8_t type = entry[0] >> 4;
|
||||||
if(type == 0 || type == 4 || type > 5)
|
if(type == 0 || type == 4 || type > 5)
|
||||||
fatalerror("Unhandled file type %x\n", type);
|
throw std::runtime_error(util::string_format("Unhandled file type %x", type));
|
||||||
return new file(m_fs, entry, key, this);
|
return new file(m_fs, entry, key, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,22 +339,22 @@ filesystem_t::dir_t fs_prodos::impl::root_dir::dir_get(uint64_t key)
|
|||||||
{
|
{
|
||||||
auto [blk, entry] = get_entry_ro(key);
|
auto [blk, entry] = get_entry_ro(key);
|
||||||
if(!blk)
|
if(!blk)
|
||||||
fatalerror("Out-of-range key on dir_get\n");
|
throw std::out_of_range("Out-of-range key on dir_get");
|
||||||
u8 type = entry[0] >> 4;
|
uint8_t type = entry[0] >> 4;
|
||||||
if(type != 0xd)
|
if(type != 0xd)
|
||||||
fatalerror("Unhandled directory type %x\n", type);
|
throw std::runtime_error(util::string_format("Unhandled directory type %x", type));
|
||||||
|
|
||||||
return new dir(m_fs, entry, r16l(entry+0x11), key, this);
|
return new dir(m_fs, entry, r16l(entry+0x11), key, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_prodos::impl::dir::dir(impl &fs, const u8 *entry, u16 base_block, u16 key, root_dir *parent_dir) : root_dir(fs, base_block), m_parent_dir(parent_dir), m_key(key)
|
fs_prodos::impl::dir::dir(impl &fs, const uint8_t *entry, uint16_t base_block, uint16_t key, root_dir *parent_dir) : root_dir(fs, base_block), m_parent_dir(parent_dir), m_key(key)
|
||||||
{
|
{
|
||||||
memcpy(m_entry, entry, 39);
|
memcpy(m_entry, entry, 39);
|
||||||
(void)m_key;
|
(void)m_key;
|
||||||
(void)m_parent_dir;
|
(void)m_parent_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_prodos::impl::file::file(impl &fs, const u8 *entry, u16 key, root_dir *parent_dir) : m_fs(fs), m_parent_dir(parent_dir), m_key(key)
|
fs_prodos::impl::file::file(impl &fs, const uint8_t *entry, uint16_t key, root_dir *parent_dir) : m_fs(fs), m_parent_dir(parent_dir), m_key(key)
|
||||||
{
|
{
|
||||||
memcpy(m_entry, entry, 39);
|
memcpy(m_entry, entry, 39);
|
||||||
(void)m_key;
|
(void)m_key;
|
||||||
@ -365,7 +368,7 @@ void fs_prodos::impl::file::drop_weak_references()
|
|||||||
fs_meta_data fs_prodos::impl::file::metadata()
|
fs_meta_data fs_prodos::impl::file::metadata()
|
||||||
{
|
{
|
||||||
fs_meta_data res;
|
fs_meta_data res;
|
||||||
u8 type = r8(m_entry);
|
uint8_t type = r8(m_entry);
|
||||||
std::string name = rstr(m_entry+1, type & 0xf);
|
std::string name = rstr(m_entry+1, type & 0xf);
|
||||||
type >>= 4;
|
type >>= 4;
|
||||||
res.set(fs_meta_name::name, name);
|
res.set(fs_meta_name::name, name);
|
||||||
@ -378,7 +381,7 @@ fs_meta_data fs_prodos::impl::file::metadata()
|
|||||||
res.set(fs_meta_name::length, r24l(m_entry + 0x15));
|
res.set(fs_meta_name::length, r24l(m_entry + 0x15));
|
||||||
|
|
||||||
else
|
else
|
||||||
fatalerror("fs_prodos::impl::file::metadata: Unhandled file type %d\n", type);
|
throw std::runtime_error(util::string_format("fs_prodos::impl::file::metadata: Unhandled file type %d", type));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -386,22 +389,22 @@ fs_meta_data fs_prodos::impl::file::metadata()
|
|||||||
fs_meta_data fs_prodos::impl::dir::metadata()
|
fs_meta_data fs_prodos::impl::dir::metadata()
|
||||||
{
|
{
|
||||||
fs_meta_data res;
|
fs_meta_data res;
|
||||||
u8 type = r8(m_entry);
|
uint8_t type = r8(m_entry);
|
||||||
std::string name = rstr(m_entry+1, type & 0xf);
|
std::string name = rstr(m_entry+1, type & 0xf);
|
||||||
res.set(fs_meta_name::name, name);
|
res.set(fs_meta_name::name, name);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> fs_prodos::impl::file::any_read_all(uint8_t type, u16 block, u32 length)
|
std::vector<uint8_t> fs_prodos::impl::file::any_read_all(uint8_t type, uint16_t block, uint32_t length)
|
||||||
{
|
{
|
||||||
std::vector<u8> data((length + 511) & ~511);
|
std::vector<uint8_t> data((length + 511) & ~511);
|
||||||
u32 nb = data.size()/512;
|
uint32_t nb = data.size()/512;
|
||||||
if(!nb)
|
if(!nb)
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
u8 *dst = data.data();
|
uint8_t *dst = data.data();
|
||||||
u8 *end = dst + data.size();
|
uint8_t *end = dst + data.size();
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case 1:
|
case 1:
|
||||||
memcpy(dst, m_fs.m_blockdev.get(block).rodata(), 512);
|
memcpy(dst, m_fs.m_blockdev.get(block).rodata(), 512);
|
||||||
@ -410,8 +413,8 @@ std::vector<u8> fs_prodos::impl::file::any_read_all(uint8_t type, u16 block, u32
|
|||||||
|
|
||||||
case 2: {
|
case 2: {
|
||||||
auto iblk = m_fs.m_blockdev.get(block);
|
auto iblk = m_fs.m_blockdev.get(block);
|
||||||
for(u32 i=0; i != 256 && dst != end; i++) {
|
for(uint32_t i=0; i != 256 && dst != end; i++) {
|
||||||
u16 blk = iblk.r8(i) | (iblk.r8(i | 0x100) << 8);
|
uint16_t blk = iblk.r8(i) | (iblk.r8(i | 0x100) << 8);
|
||||||
memcpy(dst, m_fs.m_blockdev.get(blk).rodata(), 512);
|
memcpy(dst, m_fs.m_blockdev.get(blk).rodata(), 512);
|
||||||
dst += 512;
|
dst += 512;
|
||||||
}
|
}
|
||||||
@ -420,11 +423,11 @@ std::vector<u8> fs_prodos::impl::file::any_read_all(uint8_t type, u16 block, u32
|
|||||||
|
|
||||||
case 3: {
|
case 3: {
|
||||||
auto mblk = m_fs.m_blockdev.get(block);
|
auto mblk = m_fs.m_blockdev.get(block);
|
||||||
for(u32 j=0; dst != end; j += 256) {
|
for(uint32_t j=0; dst != end; j += 256) {
|
||||||
u32 idx = j/256;
|
uint32_t idx = j/256;
|
||||||
auto iblk = m_fs.m_blockdev.get(mblk.r8(idx) | (mblk.r8(idx | 0x100) << 8));
|
auto iblk = m_fs.m_blockdev.get(mblk.r8(idx) | (mblk.r8(idx | 0x100) << 8));
|
||||||
for(u32 i=0; i != 256 && dst != end; i++) {
|
for(uint32_t i=0; i != 256 && dst != end; i++) {
|
||||||
u16 blk = iblk.r8(i) | (iblk.r8(i | 0x100) << 8);
|
uint16_t blk = iblk.r8(i) | (iblk.r8(i | 0x100) << 8);
|
||||||
memcpy(dst, m_fs.m_blockdev.get(blk).rodata(), 512);
|
memcpy(dst, m_fs.m_blockdev.get(blk).rodata(), 512);
|
||||||
dst += 512;
|
dst += 512;
|
||||||
}
|
}
|
||||||
@ -433,16 +436,16 @@ std::vector<u8> fs_prodos::impl::file::any_read_all(uint8_t type, u16 block, u32
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fatalerror("fs_prodos::impl::file::get_file_blocks: unknown file type %d\n", type);
|
throw std::runtime_error(util::string_format("fs_prodos::impl::file::get_file_blocks: unknown file type %d", type));
|
||||||
}
|
}
|
||||||
|
|
||||||
data.resize(length);
|
data.resize(length);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> fs_prodos::impl::file::read_all()
|
std::vector<uint8_t> fs_prodos::impl::file::read_all()
|
||||||
{
|
{
|
||||||
u8 type = r8(m_entry) >> 4;
|
uint8_t type = r8(m_entry) >> 4;
|
||||||
if(type >= 1 && type <= 3)
|
if(type >= 1 && type <= 3)
|
||||||
return any_read_all(type, r16l(m_entry+0x11), r24l(m_entry + 0x15));
|
return any_read_all(type, r16l(m_entry+0x11), r24l(m_entry + 0x15));
|
||||||
|
|
||||||
@ -451,17 +454,17 @@ std::vector<u8> fs_prodos::impl::file::read_all()
|
|||||||
return any_read_all(kblk.r8(0x000), kblk.r16l(0x001), kblk.r24l(0x005));
|
return any_read_all(kblk.r8(0x000), kblk.r16l(0x001), kblk.r24l(0x005));
|
||||||
|
|
||||||
} else
|
} else
|
||||||
fatalerror("fs_prodos::impl::file::read_all: Unhandled file type %d\n", type);
|
throw std::runtime_error(util::string_format("fs_prodos::impl::file::read_all: Unhandled file type %d", type));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> fs_prodos::impl::file::rsrc_read_all()
|
std::vector<uint8_t> fs_prodos::impl::file::rsrc_read_all()
|
||||||
{
|
{
|
||||||
u8 type = r8(m_entry) >> 4;
|
uint8_t type = r8(m_entry) >> 4;
|
||||||
|
|
||||||
if(type == 5) {
|
if(type == 5) {
|
||||||
auto kblk = m_fs.m_blockdev.get(r16l(m_entry+0x11));
|
auto kblk = m_fs.m_blockdev.get(r16l(m_entry+0x11));
|
||||||
return any_read_all(kblk.r8(0x100), kblk.r16l(0x101), kblk.r24l(0x105));
|
return any_read_all(kblk.r8(0x100), kblk.r16l(0x101), kblk.r24l(0x105));
|
||||||
|
|
||||||
} else
|
} else
|
||||||
fatalerror("fs_prodos::impl::file::rsrc_blocks: Unhandled file type %d\n", type);
|
throw std::runtime_error(util::string_format("fs_prodos::impl::file::rsrc_blocks: Unhandled file type %d", type));
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
class root_dir : public idir_t {
|
class root_dir : public idir_t {
|
||||||
public:
|
public:
|
||||||
root_dir(impl &fs, u16 base_block) : m_fs(fs), m_base_block(base_block) { }
|
root_dir(impl &fs, uint16_t base_block) : m_fs(fs), m_base_block(base_block) { }
|
||||||
virtual ~root_dir() = default;
|
virtual ~root_dir() = default;
|
||||||
|
|
||||||
virtual void drop_weak_references() override;
|
virtual void drop_weak_references() override;
|
||||||
@ -28,43 +28,43 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
impl &m_fs;
|
impl &m_fs;
|
||||||
u16 m_base_block;
|
uint16_t m_base_block;
|
||||||
|
|
||||||
std::pair<fsblk_t::block_t, const u8 *> get_entry_ro(uint64_t key);
|
std::pair<fsblk_t::block_t, const uint8_t *> get_entry_ro(uint64_t key);
|
||||||
std::pair<fsblk_t::block_t, u8 *> get_entry(uint64_t key);
|
std::pair<fsblk_t::block_t, uint8_t *> get_entry(uint64_t key);
|
||||||
};
|
};
|
||||||
|
|
||||||
class dir : public root_dir {
|
class dir : public root_dir {
|
||||||
public:
|
public:
|
||||||
dir(impl &fs, const u8 *entry, u16 base_block, u16 key, root_dir *parent_dir);
|
dir(impl &fs, const uint8_t *entry, uint16_t base_block, uint16_t key, root_dir *parent_dir);
|
||||||
virtual ~dir() = default;
|
virtual ~dir() = default;
|
||||||
|
|
||||||
virtual fs_meta_data metadata() override;
|
virtual fs_meta_data metadata() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
root_dir *m_parent_dir;
|
root_dir *m_parent_dir;
|
||||||
u16 m_key;
|
uint16_t m_key;
|
||||||
u8 m_entry[39];
|
uint8_t m_entry[39];
|
||||||
};
|
};
|
||||||
|
|
||||||
class file : public ifile_t {
|
class file : public ifile_t {
|
||||||
public:
|
public:
|
||||||
file(impl &fs, const u8 *entry, u16 key, root_dir *parent_dir);
|
file(impl &fs, const uint8_t *entry, uint16_t key, root_dir *parent_dir);
|
||||||
virtual ~file() = default;
|
virtual ~file() = default;
|
||||||
|
|
||||||
virtual void drop_weak_references() override;
|
virtual void drop_weak_references() override;
|
||||||
|
|
||||||
virtual fs_meta_data metadata() override;
|
virtual fs_meta_data metadata() override;
|
||||||
virtual std::vector<u8> read_all() override;
|
virtual std::vector<uint8_t> read_all() override;
|
||||||
virtual std::vector<u8> rsrc_read_all() override;
|
virtual std::vector<uint8_t> rsrc_read_all() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
impl &m_fs;
|
impl &m_fs;
|
||||||
root_dir *m_parent_dir;
|
root_dir *m_parent_dir;
|
||||||
u16 m_key;
|
uint16_t m_key;
|
||||||
u8 m_entry[39];
|
uint8_t m_entry[39];
|
||||||
|
|
||||||
std::vector<u8> any_read_all(uint8_t type, u16 block, u32 length);
|
std::vector<uint8_t> any_read_all(uint8_t type, uint16_t block, uint32_t length);
|
||||||
};
|
};
|
||||||
|
|
||||||
impl(fsblk_t &blockdev);
|
impl(fsblk_t &blockdev);
|
||||||
@ -77,11 +77,11 @@ public:
|
|||||||
|
|
||||||
void drop_root_ref();
|
void drop_root_ref();
|
||||||
|
|
||||||
static util::arbitrary_datetime prodos_to_dt(u32 date);
|
static util::arbitrary_datetime prodos_to_dt(uint32_t date);
|
||||||
std::vector<fs_dir_entry> contents(u16 block);
|
std::vector<fs_dir_entry> contents(uint16_t block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const u8 boot[512];
|
static const uint8_t boot[512];
|
||||||
|
|
||||||
dir_t m_root;
|
dir_t m_root;
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
// Creation of unformatted floppy images
|
// Creation of unformatted floppy images
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "fs_unformatted.h"
|
#include "fs_unformatted.h"
|
||||||
|
|
||||||
const fs_unformatted FS_UNFORMATTED;
|
const fs_unformatted FS_UNFORMATTED;
|
||||||
@ -20,6 +19,8 @@ const char *fs_unformatted::description() const
|
|||||||
|
|
||||||
void fs_unformatted::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const
|
void fs_unformatted::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const
|
||||||
{
|
{
|
||||||
|
using u32 = std::uint32_t;
|
||||||
|
|
||||||
bool all = form_factor == floppy_image::FF_UNKNOWN;
|
bool all = form_factor == floppy_image::FF_UNKNOWN;
|
||||||
u32 best_8 =
|
u32 best_8 =
|
||||||
form_factor == floppy_image::FF_8 ?
|
form_factor == floppy_image::FF_8 ?
|
||||||
@ -83,7 +84,7 @@ void fs_unformatted::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, co
|
|||||||
fe.add_raw("u3ssdd", FSI_35_SSDD, "Unformatted 3\" single-sided double-density");
|
fe.add_raw("u3ssdd", FSI_35_SSDD, "Unformatted 3\" single-sided double-density");
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_unformatted::format(u32 key, floppy_image *image)
|
void fs_unformatted::format(uint32_t key, floppy_image *image)
|
||||||
{
|
{
|
||||||
switch(key) {
|
switch(key) {
|
||||||
case FSI_8_DSDD: image->set_form_variant(floppy_image::FF_8, floppy_image::DSDD); break;
|
case FSI_8_DSDD: image->set_form_variant(floppy_image::FF_8, floppy_image::DSDD); break;
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
virtual const char *name() const override;
|
virtual const char *name() const override;
|
||||||
virtual const char *description() const override;
|
virtual const char *description() const override;
|
||||||
|
|
||||||
static void format(u32 key, floppy_image *image);
|
static void format(uint32_t key, floppy_image *image);
|
||||||
|
|
||||||
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
|
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
|
||||||
virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override;
|
virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override;
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
// Management of VTech images
|
// Management of VTech images
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "fs_vtech.h"
|
#include "fs_vtech.h"
|
||||||
#include "vt_dsk.h"
|
#include "vt_dsk.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
const fs_vtech FS_VTECH;
|
const fs_vtech FS_VTECH;
|
||||||
|
|
||||||
// Floppy only, format is 40 tracks, 1 head, 16 sectors numbered 0-15, 256 bytes/sector.
|
// Floppy only, format is 40 tracks, 1 head, 16 sectors numbered 0-15, 256 bytes/sector.
|
||||||
@ -126,9 +127,9 @@ std::vector<fs_dir_entry> fs_vtech::impl::root_dir::contents()
|
|||||||
uint64_t id = 0;
|
uint64_t id = 0;
|
||||||
for(int sect = 0; sect != 14; sect++) {
|
for(int sect = 0; sect != 14; sect++) {
|
||||||
auto bdir = m_fs.m_blockdev.get(sect);
|
auto bdir = m_fs.m_blockdev.get(sect);
|
||||||
for(u32 i = 0; i != 8; i ++) {
|
for(uint32_t i = 0; i != 8; i ++) {
|
||||||
u32 off = i*16;
|
uint32_t off = i*16;
|
||||||
u8 type = bdir.r8(off);
|
uint8_t type = bdir.r8(off);
|
||||||
if(type != 'T' && type != 'B')
|
if(type != 'T' && type != 'B')
|
||||||
continue;
|
continue;
|
||||||
if(bdir.r8(off+1) != ':')
|
if(bdir.r8(off+1) != ':')
|
||||||
@ -144,14 +145,14 @@ std::vector<fs_dir_entry> fs_vtech::impl::root_dir::contents()
|
|||||||
filesystem_t::file_t fs_vtech::impl::root_dir::file_get(uint64_t key)
|
filesystem_t::file_t fs_vtech::impl::root_dir::file_get(uint64_t key)
|
||||||
{
|
{
|
||||||
if(key >= 15*8)
|
if(key >= 15*8)
|
||||||
fatalerror("Key out of range\n");
|
throw std::out_of_range("Key out of range");
|
||||||
|
|
||||||
auto bdir = m_fs.m_blockdev.get(key >> 3);
|
auto bdir = m_fs.m_blockdev.get(key >> 3);
|
||||||
int off = (key & 7) << 4;
|
int off = (key & 7) << 4;
|
||||||
return file_t(new file(m_fs, this, bdir.rodata() + off, key));
|
return file_t(new file(m_fs, this, bdir.rodata() + off, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_vtech::impl::root_dir::update_file(u16 key, const u8 *entry)
|
void fs_vtech::impl::root_dir::update_file(uint16_t key, const uint8_t *entry)
|
||||||
{
|
{
|
||||||
auto bdir = m_fs.m_blockdev.get(key >> 3);
|
auto bdir = m_fs.m_blockdev.get(key >> 3);
|
||||||
int off = (key & 7) << 4;
|
int off = (key & 7) << 4;
|
||||||
@ -160,10 +161,10 @@ void fs_vtech::impl::root_dir::update_file(u16 key, const u8 *entry)
|
|||||||
|
|
||||||
filesystem_t::dir_t fs_vtech::impl::root_dir::dir_get(uint64_t key)
|
filesystem_t::dir_t fs_vtech::impl::root_dir::dir_get(uint64_t key)
|
||||||
{
|
{
|
||||||
fatalerror("Directories not supported\n");
|
throw std::logic_error("Directories not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_vtech::impl::file::file(impl &fs, root_dir *dir, const u8 *entry, u16 key) : m_fs(fs), m_dir(dir), m_key(key)
|
fs_vtech::impl::file::file(impl &fs, root_dir *dir, const uint8_t *entry, uint16_t key) : m_fs(fs), m_dir(dir), m_key(key)
|
||||||
{
|
{
|
||||||
memcpy(m_entry, entry, 16);
|
memcpy(m_entry, entry, 16);
|
||||||
}
|
}
|
||||||
@ -184,13 +185,13 @@ fs_meta_data fs_vtech::impl::file::metadata()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> fs_vtech::impl::file::read_all()
|
std::vector<uint8_t> fs_vtech::impl::file::read_all()
|
||||||
{
|
{
|
||||||
u8 track = m_entry[0xa];
|
uint8_t track = m_entry[0xa];
|
||||||
u8 sector = m_entry[0xb];
|
uint8_t sector = m_entry[0xb];
|
||||||
int len = ((r16l(m_entry + 0xe) - r16l(m_entry + 0xc)) & 0xffff) + 1;
|
int len = ((r16l(m_entry + 0xe) - r16l(m_entry + 0xc)) & 0xffff) + 1;
|
||||||
|
|
||||||
std::vector<u8> data(len, 0);
|
std::vector<uint8_t> data(len, 0);
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
while(pos < len) {
|
while(pos < len) {
|
||||||
if(track >= 40 || sector >= 16)
|
if(track >= 40 || sector >= 16)
|
||||||
@ -213,9 +214,9 @@ fs_vtech::impl::file_t fs_vtech::impl::root_dir::file_create(const fs_meta_data
|
|||||||
for(int sect = 0; sect != 14; sect++) {
|
for(int sect = 0; sect != 14; sect++) {
|
||||||
auto bdir = m_fs.m_blockdev.get(sect);
|
auto bdir = m_fs.m_blockdev.get(sect);
|
||||||
uint64_t id = 0;
|
uint64_t id = 0;
|
||||||
for(u32 i = 0; i != 16; i ++) {
|
for(uint32_t i = 0; i != 16; i ++) {
|
||||||
u32 off = i*16;
|
uint32_t off = i*16;
|
||||||
u8 type = bdir.r8(off);
|
uint8_t type = bdir.r8(off);
|
||||||
if(type != 'T' && type != 'B') {
|
if(type != 'T' && type != 'B') {
|
||||||
std::string fname = info.get_string(fs_meta_name::name, "");
|
std::string fname = info.get_string(fs_meta_name::name, "");
|
||||||
fname.resize(8, ' ');
|
fname.resize(8, ' ');
|
||||||
@ -239,23 +240,23 @@ void fs_vtech::impl::root_dir::file_delete(uint64_t key)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_vtech::impl::file::replace(const std::vector<u8> &data)
|
void fs_vtech::impl::file::replace(const std::vector<uint8_t> &data)
|
||||||
{
|
{
|
||||||
u32 cur_len = ((r16l(m_entry + 0xe) - r16l(m_entry + 0xc) + 1) & 0xffff);
|
uint32_t cur_len = ((r16l(m_entry + 0xe) - r16l(m_entry + 0xc) + 1) & 0xffff);
|
||||||
u32 new_len = data.size();
|
uint32_t new_len = data.size();
|
||||||
if(new_len > 65535)
|
if(new_len > 65535)
|
||||||
new_len = 65535;
|
new_len = 65535;
|
||||||
u32 cur_ns = (cur_len + 125)/126;
|
uint32_t cur_ns = (cur_len + 125)/126;
|
||||||
u32 need_ns = (new_len + 125) / 126;
|
uint32_t need_ns = (new_len + 125) / 126;
|
||||||
|
|
||||||
// Enough space?
|
// Enough space?
|
||||||
if(cur_ns < need_ns && m_fs.free_block_count() < need_ns - cur_ns)
|
if(cur_ns < need_ns && m_fs.free_block_count() < need_ns - cur_ns)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u8 track = m_entry[0xa];
|
uint8_t track = m_entry[0xa];
|
||||||
u8 sector = m_entry[0xb];
|
uint8_t sector = m_entry[0xb];
|
||||||
std::vector<std::pair<u8, u8>> tofree;
|
std::vector<std::pair<uint8_t, uint8_t>> tofree;
|
||||||
for(u32 i = 0; i != cur_ns; i++) {
|
for(uint32_t i = 0; i != cur_ns; i++) {
|
||||||
tofree.emplace_back(std::make_pair(track, sector));
|
tofree.emplace_back(std::make_pair(track, sector));
|
||||||
auto dblk = m_fs.m_blockdev.get(track*16 + sector);
|
auto dblk = m_fs.m_blockdev.get(track*16 + sector);
|
||||||
track = dblk.r8(126);
|
track = dblk.r8(126);
|
||||||
@ -264,10 +265,10 @@ void fs_vtech::impl::file::replace(const std::vector<u8> &data)
|
|||||||
|
|
||||||
m_fs.free_blocks(tofree);
|
m_fs.free_blocks(tofree);
|
||||||
|
|
||||||
std::vector<std::pair<u8, u8>> blocks = m_fs.allocate_blocks(need_ns);
|
std::vector<std::pair<uint8_t, uint8_t>> blocks = m_fs.allocate_blocks(need_ns);
|
||||||
for(u32 i=0; i != need_ns; i ++) {
|
for(uint32_t i=0; i != need_ns; i ++) {
|
||||||
auto dblk = m_fs.m_blockdev.get(blocks[i].first * 16 + blocks[i].second);
|
auto dblk = m_fs.m_blockdev.get(blocks[i].first * 16 + blocks[i].second);
|
||||||
u32 len = new_len - i*126;
|
uint32_t len = new_len - i*126;
|
||||||
if(len > 126)
|
if(len > 126)
|
||||||
len = 126;
|
len = 126;
|
||||||
else if(len < 126)
|
else if(len < 126)
|
||||||
@ -280,7 +281,7 @@ void fs_vtech::impl::file::replace(const std::vector<u8> &data)
|
|||||||
dblk.w16l(126, 0);
|
dblk.w16l(126, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 end_address = (r16l(m_entry + 0xc) + data.size() - 1) & 0xffff;
|
uint16_t end_address = (r16l(m_entry + 0xc) + data.size() - 1) & 0xffff;
|
||||||
w16l(m_entry + 0xe, end_address);
|
w16l(m_entry + 0xe, end_address);
|
||||||
if(need_ns) {
|
if(need_ns) {
|
||||||
w8(m_entry + 0xa, blocks[0].first);
|
w8(m_entry + 0xa, blocks[0].first);
|
||||||
@ -309,25 +310,25 @@ void fs_vtech::impl::file::metadata_change(const fs_meta_data &info)
|
|||||||
wstr(m_entry+0x2, name);
|
wstr(m_entry+0x2, name);
|
||||||
}
|
}
|
||||||
if(info.has(fs_meta_name::loading_address)) {
|
if(info.has(fs_meta_name::loading_address)) {
|
||||||
u16 new_loading = info.get_number(fs_meta_name::loading_address);
|
uint16_t new_loading = info.get_number(fs_meta_name::loading_address);
|
||||||
u16 new_end = r16l(m_entry + 0xe) - r16l(m_entry + 0xc) + new_loading;
|
uint16_t new_end = r16l(m_entry + 0xe) - r16l(m_entry + 0xc) + new_loading;
|
||||||
w16l(m_entry + 0xc, new_loading);
|
w16l(m_entry + 0xc, new_loading);
|
||||||
w16l(m_entry + 0xe, new_end);
|
w16l(m_entry + 0xe, new_end);
|
||||||
}
|
}
|
||||||
m_dir->update_file(m_key, m_entry);
|
m_dir->update_file(m_key, m_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<u8, u8>> fs_vtech::impl::allocate_blocks(u32 count)
|
std::vector<std::pair<uint8_t, uint8_t>> fs_vtech::impl::allocate_blocks(uint32_t count)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<u8, u8>> blocks;
|
std::vector<std::pair<uint8_t, uint8_t>> blocks;
|
||||||
if(free_block_count() < count)
|
if(free_block_count() < count)
|
||||||
return blocks;
|
return blocks;
|
||||||
|
|
||||||
auto fmap = m_blockdev.get(15);
|
auto fmap = m_blockdev.get(15);
|
||||||
for(u8 track = 1; track != 40; track++)
|
for(uint8_t track = 1; track != 40; track++)
|
||||||
for(u8 sector = 0; sector != 16; sector++) {
|
for(uint8_t sector = 0; sector != 16; sector++) {
|
||||||
u32 off = (track-1)*2 + (sector / 8);
|
uint32_t off = (track-1)*2 + (sector / 8);
|
||||||
u32 bit = 1 << (sector & 7);
|
uint32_t bit = 1 << (sector & 7);
|
||||||
if(!(fmap.r8(off) & bit)) {
|
if(!(fmap.r8(off) & bit)) {
|
||||||
fmap.w8(off, fmap.r8(off) | bit);
|
fmap.w8(off, fmap.r8(off) | bit);
|
||||||
blocks.emplace_back(std::make_pair(track, sector));
|
blocks.emplace_back(std::make_pair(track, sector));
|
||||||
@ -338,24 +339,24 @@ std::vector<std::pair<u8, u8>> fs_vtech::impl::allocate_blocks(u32 count)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_vtech::impl::free_blocks(const std::vector<std::pair<u8, u8>> &blocks)
|
void fs_vtech::impl::free_blocks(const std::vector<std::pair<uint8_t, uint8_t>> &blocks)
|
||||||
{
|
{
|
||||||
auto fmap = m_blockdev.get(15);
|
auto fmap = m_blockdev.get(15);
|
||||||
for(auto ref : blocks) {
|
for(auto ref : blocks) {
|
||||||
u8 track = ref.first;
|
uint8_t track = ref.first;
|
||||||
u8 sector = ref.second;
|
uint8_t sector = ref.second;
|
||||||
u32 off = (track-1)*2 + (sector / 8);
|
uint32_t off = (track-1)*2 + (sector / 8);
|
||||||
u32 bit = 1 << (sector & 7);
|
uint32_t bit = 1 << (sector & 7);
|
||||||
fmap.w8(off, fmap.r8(off) & ~bit);
|
fmap.w8(off, fmap.r8(off) & ~bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 fs_vtech::impl::free_block_count()
|
uint32_t fs_vtech::impl::free_block_count()
|
||||||
{
|
{
|
||||||
auto fmap = m_blockdev.get(15);
|
auto fmap = m_blockdev.get(15);
|
||||||
u32 nf = 0;
|
uint32_t nf = 0;
|
||||||
for(u32 off = 0; off != (40-1)*2; off++) {
|
for(uint32_t off = 0; off != (40-1)*2; off++) {
|
||||||
u8 m = fmap.r8(off);
|
uint8_t m = fmap.r8(off);
|
||||||
// Count 1 bits;
|
// Count 1 bits;
|
||||||
m = ((m & 0xaa) >> 1) | (m & 0x55);
|
m = ((m & 0xaa) >> 1) | (m & 0x55);
|
||||||
m = ((m & 0xcc) >> 2) | (m & 0x33);
|
m = ((m & 0xcc) >> 2) | (m & 0x33);
|
||||||
|
@ -29,31 +29,31 @@ public:
|
|||||||
virtual file_t file_create(const fs_meta_data &info) override;
|
virtual file_t file_create(const fs_meta_data &info) override;
|
||||||
virtual void file_delete(uint64_t key) override;
|
virtual void file_delete(uint64_t key) override;
|
||||||
|
|
||||||
void update_file(u16 key, const u8 *entry);
|
void update_file(uint16_t key, const uint8_t *entry);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
impl &m_fs;
|
impl &m_fs;
|
||||||
|
|
||||||
std::pair<fsblk_t::block_t, u32> get_dir_block(uint64_t key);
|
std::pair<fsblk_t::block_t, uint32_t> get_dir_block(uint64_t key);
|
||||||
};
|
};
|
||||||
|
|
||||||
class file : public ifile_t {
|
class file : public ifile_t {
|
||||||
public:
|
public:
|
||||||
file(impl &fs, root_dir *dir, const u8 *entry, u16 key);
|
file(impl &fs, root_dir *dir, const uint8_t *entry, uint16_t key);
|
||||||
virtual ~file() = default;
|
virtual ~file() = default;
|
||||||
|
|
||||||
virtual void drop_weak_references() override;
|
virtual void drop_weak_references() override;
|
||||||
|
|
||||||
virtual fs_meta_data metadata() override;
|
virtual fs_meta_data metadata() override;
|
||||||
virtual void metadata_change(const fs_meta_data &info) override;
|
virtual void metadata_change(const fs_meta_data &info) override;
|
||||||
virtual std::vector<u8> read_all() override;
|
virtual std::vector<uint8_t> read_all() override;
|
||||||
virtual void replace(const std::vector<u8> &data) override;
|
virtual void replace(const std::vector<uint8_t> &data) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
impl &m_fs;
|
impl &m_fs;
|
||||||
root_dir *m_dir;
|
root_dir *m_dir;
|
||||||
u16 m_key;
|
uint16_t m_key;
|
||||||
u8 m_entry[18];
|
uint8_t m_entry[18];
|
||||||
};
|
};
|
||||||
|
|
||||||
impl(fsblk_t &blockdev);
|
impl(fsblk_t &blockdev);
|
||||||
@ -66,9 +66,9 @@ public:
|
|||||||
|
|
||||||
void drop_root_ref();
|
void drop_root_ref();
|
||||||
|
|
||||||
std::vector<std::pair<u8, u8>> allocate_blocks(u32 count);
|
std::vector<std::pair<uint8_t, uint8_t>> allocate_blocks(uint32_t count);
|
||||||
void free_blocks(const std::vector<std::pair<u8, u8>> &blocks);
|
void free_blocks(const std::vector<std::pair<uint8_t, uint8_t>> &blocks);
|
||||||
u32 free_block_count();
|
uint32_t free_block_count();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dir_t m_root;
|
dir_t m_root;
|
||||||
|
@ -3,9 +3,13 @@
|
|||||||
|
|
||||||
// Block device on vector<uint8_t>
|
// Block device on vector<uint8_t>
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "fsblk_vec.h"
|
#include "fsblk_vec.h"
|
||||||
|
|
||||||
|
#include "strformat.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
const uint8_t *fsblk_vec_t::blk_t::rodata()
|
const uint8_t *fsblk_vec_t::blk_t::rodata()
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
@ -28,7 +32,7 @@ uint32_t fsblk_vec_t::block_count() const
|
|||||||
fsblk_t::block_t fsblk_vec_t::get(uint32_t id)
|
fsblk_t::block_t fsblk_vec_t::get(uint32_t id)
|
||||||
{
|
{
|
||||||
if(id >= block_count())
|
if(id >= block_count())
|
||||||
fatalerror("Block number overflow: requiring block %d on device of size %d (%d bytes, block size %d)\n", id, block_count(), m_data.size(), m_block_size);
|
throw std::out_of_range(util::string_format("Block number overflow: requiring block %d on device of size %d (%d bytes, block size %d)", id, block_count(), m_data.size(), m_block_size));
|
||||||
return block_t(new blk_t(m_data.data() + m_block_size*id, m_block_size));
|
return block_t(new blk_t(m_data.data() + m_block_size*id, m_block_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
src/lib/formats/fsmeta.cpp
Normal file
43
src/lib/formats/fsmeta.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
// Filesystem metadata management
|
||||||
|
|
||||||
|
#include "fsmeta.h"
|
||||||
|
|
||||||
|
#include "strformat.h"
|
||||||
|
|
||||||
|
const char *fs_meta_data::entry_name(fs_meta_name name)
|
||||||
|
{
|
||||||
|
switch(name) {
|
||||||
|
case fs_meta_name::basic: return "basic";
|
||||||
|
case fs_meta_name::creation_date: return "creation_date";
|
||||||
|
case fs_meta_name::length: return "length";
|
||||||
|
case fs_meta_name::loading_address: return "loading_address";
|
||||||
|
case fs_meta_name::locked: return "locked";
|
||||||
|
case fs_meta_name::modification_date: return "modification_date";
|
||||||
|
case fs_meta_name::name: return "name";
|
||||||
|
case fs_meta_name::os_minimum_version: return "os_minimum_version";
|
||||||
|
case fs_meta_name::os_version: return "os_version";
|
||||||
|
case fs_meta_name::rsrc_length: return "rsrc_length";
|
||||||
|
case fs_meta_name::sequential: return "sequential";
|
||||||
|
case fs_meta_name::size_in_blocks: return "size_in_blocks";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fs_meta::to_string(fs_meta_type type, const fs_meta &m)
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case fs_meta_type::string: return m.as_string();
|
||||||
|
case fs_meta_type::number: return util::string_format("0x%x", m.as_number());
|
||||||
|
case fs_meta_type::flag: return m.as_flag() ? "t" : "f";
|
||||||
|
case fs_meta_type::date: {
|
||||||
|
auto dt = m.as_date();
|
||||||
|
return util::string_format("%04d-%02d-%02d %02d:%02d:%02d",
|
||||||
|
dt.year, dt.month, dt.day_of_month,
|
||||||
|
dt.hour, dt.minute, dt.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::string("");
|
||||||
|
}
|
107
src/lib/formats/fsmeta.h
Normal file
107
src/lib/formats/fsmeta.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
// Filesystem metadata management
|
||||||
|
|
||||||
|
#ifndef MAME_FORMATS_FSMETA_H
|
||||||
|
#define MAME_FORMATS_FSMETA_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "timeconv.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
enum class fs_meta_name {
|
||||||
|
basic,
|
||||||
|
creation_date,
|
||||||
|
length,
|
||||||
|
loading_address,
|
||||||
|
locked,
|
||||||
|
modification_date,
|
||||||
|
name,
|
||||||
|
os_minimum_version,
|
||||||
|
os_version,
|
||||||
|
rsrc_length,
|
||||||
|
sequential,
|
||||||
|
size_in_blocks,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class fs_meta_type {
|
||||||
|
date,
|
||||||
|
flag,
|
||||||
|
number,
|
||||||
|
string,
|
||||||
|
};
|
||||||
|
|
||||||
|
class fs_meta {
|
||||||
|
public:
|
||||||
|
static std::string to_string(fs_meta_type type, const fs_meta &m);
|
||||||
|
static fs_meta from_string(fs_meta_type type, std::string value);
|
||||||
|
|
||||||
|
fs_meta() { value = false; }
|
||||||
|
fs_meta(std::string str) { value = str; }
|
||||||
|
fs_meta(bool b) { value = b; }
|
||||||
|
fs_meta(int32_t num) { value = uint64_t(num); }
|
||||||
|
fs_meta(uint32_t num) { value = uint64_t(num); }
|
||||||
|
fs_meta(int64_t num) { value = uint64_t(num); }
|
||||||
|
fs_meta(uint64_t num) { value = num; }
|
||||||
|
fs_meta(util::arbitrary_datetime dt) { value = dt; }
|
||||||
|
|
||||||
|
util::arbitrary_datetime as_date() const { return *std::get_if<util::arbitrary_datetime>(&value); }
|
||||||
|
bool as_flag() const { return *std::get_if<bool>(&value); }
|
||||||
|
uint64_t as_number() const { return *std::get_if<uint64_t>(&value); }
|
||||||
|
std::string as_string() const { return *std::get_if<std::string>(&value); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::variant<std::string, uint64_t, bool, util::arbitrary_datetime> value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class fs_meta_data {
|
||||||
|
public:
|
||||||
|
std::unordered_map<fs_meta_name, fs_meta> meta;
|
||||||
|
|
||||||
|
static const char *entry_name(fs_meta_name name);
|
||||||
|
|
||||||
|
bool has(fs_meta_name name) const { return meta.find(name) != meta.end(); }
|
||||||
|
bool empty() const { return meta.empty(); }
|
||||||
|
|
||||||
|
void set(fs_meta_name name, const fs_meta &val) { meta[name] = val; }
|
||||||
|
void set(fs_meta_name name, std::string str) { set(name, fs_meta(str)); }
|
||||||
|
void set(fs_meta_name name, bool b) { set(name, fs_meta(b)); }
|
||||||
|
void set(fs_meta_name name, int32_t num) { set(name, fs_meta(num)); }
|
||||||
|
void set(fs_meta_name name, uint32_t num) { set(name, fs_meta(num)); }
|
||||||
|
void set(fs_meta_name name, int64_t num) { set(name, fs_meta(num)); }
|
||||||
|
void set(fs_meta_name name, uint64_t num) { set(name, fs_meta(num)); }
|
||||||
|
void set(fs_meta_name name, util::arbitrary_datetime dt) { set(name, fs_meta(dt)); }
|
||||||
|
void set_now(fs_meta_name name) { set(name, fs_meta(util::arbitrary_datetime::now())); }
|
||||||
|
|
||||||
|
fs_meta get(fs_meta_name name) const { auto i = meta.find(name); assert(i != meta.end()); return i->second; }
|
||||||
|
util::arbitrary_datetime get_date(fs_meta_name name, util::arbitrary_datetime def = util::arbitrary_datetime::now()) const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_date(); }
|
||||||
|
bool get_flag(fs_meta_name name, bool def = false) const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_flag(); }
|
||||||
|
uint64_t get_number(fs_meta_name name, uint64_t def = 0) const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_number(); }
|
||||||
|
std::string get_string(fs_meta_name name, std::string def = "") const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_string(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fs_meta_description {
|
||||||
|
fs_meta_name m_name;
|
||||||
|
fs_meta_type m_type;
|
||||||
|
fs_meta m_default;
|
||||||
|
bool m_ro;
|
||||||
|
std::function<void (const fs_meta &)> m_validator;
|
||||||
|
const char *m_tooltip;
|
||||||
|
|
||||||
|
fs_meta_description(fs_meta_name name, fs_meta_type type, int def, bool ro, std::function<void (fs_meta)> validator, const char *tooltip) :
|
||||||
|
m_name(name), m_type(type), m_default(uint64_t(def)), m_ro(ro), m_validator(validator), m_tooltip(tooltip)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename T> fs_meta_description(fs_meta_name name, fs_meta_type type, T def, bool ro, std::function<void (fs_meta)> validator, const char *tooltip) :
|
||||||
|
m_name(name), m_type(type), m_default(def), m_ro(ro), m_validator(validator), m_tooltip(tooltip)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAME_FORMATS_FSMETA_H
|
@ -5,9 +5,12 @@
|
|||||||
|
|
||||||
// Currently limited to floppies and creation of preformatted images
|
// Currently limited to floppies and creation of preformatted images
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "fsmgr.h"
|
#include "fsmgr.h"
|
||||||
|
|
||||||
|
#include "strformat.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
void fs_refcounted_inner::ref()
|
void fs_refcounted_inner::ref()
|
||||||
{
|
{
|
||||||
m_ref ++;
|
m_ref ++;
|
||||||
@ -100,17 +103,17 @@ char filesystem_manager_t::directory_separator() const
|
|||||||
|
|
||||||
void filesystem_t::format(const fs_meta_data &meta)
|
void filesystem_t::format(const fs_meta_data &meta)
|
||||||
{
|
{
|
||||||
fatalerror("format called on a filesystem not supporting it.\n");
|
throw std::logic_error("format called on a filesystem not supporting it");
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystem_t::dir_t filesystem_t::root()
|
filesystem_t::dir_t filesystem_t::root()
|
||||||
{
|
{
|
||||||
fatalerror("root called on a filesystem not supporting it.\n");
|
throw std::logic_error("root called on a filesystem not supporting it");
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_meta_data filesystem_t::metadata()
|
fs_meta_data filesystem_t::metadata()
|
||||||
{
|
{
|
||||||
fatalerror("filesystem_t::metadata called on a filesystem not supporting it.\n");
|
throw std::logic_error("filesystem_t::metadata called on a filesystem not supporting it");
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::set_block_size(uint32_t block_size)
|
void fsblk_t::set_block_size(uint32_t block_size)
|
||||||
@ -122,24 +125,24 @@ void fsblk_t::set_block_size(uint32_t block_size)
|
|||||||
uint8_t *fsblk_t::iblock_t::offset(const char *function, uint32_t off, uint32_t size)
|
uint8_t *fsblk_t::iblock_t::offset(const char *function, uint32_t off, uint32_t size)
|
||||||
{
|
{
|
||||||
if(off + size > m_size)
|
if(off + size > m_size)
|
||||||
fatalerror("block_t::%s out-of-block access, offset=%d, size=%d, block size=%d\n", function, off, size, m_size);
|
throw std::out_of_range(util::string_format("block_t::%s out-of-block access, offset=%d, size=%d, block size=%d", function, off, size, m_size));
|
||||||
return data() + off;
|
return data() + off;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *fsblk_t::iblock_t::rooffset(const char *function, uint32_t off, uint32_t size)
|
const uint8_t *fsblk_t::iblock_t::rooffset(const char *function, uint32_t off, uint32_t size)
|
||||||
{
|
{
|
||||||
if(off + size > m_size)
|
if(off + size > m_size)
|
||||||
fatalerror("block_t::%s out-of-block read access, offset=%d, size=%d, block size=%d\n", function, off, size, m_size);
|
throw std::out_of_range(util::string_format("block_t::%s out-of-block read access, offset=%d, size=%d, block size=%d\n", function, off, size, m_size));
|
||||||
return rodata() + off;
|
return rodata() + off;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::block_t::copy(u32 offset, const uint8_t *src, u32 size)
|
void fsblk_t::block_t::copy(uint32_t offset, const uint8_t *src, uint32_t size)
|
||||||
{
|
{
|
||||||
uint8_t *blk = m_object->offset("copy", offset, size);
|
uint8_t *blk = m_object->offset("copy", offset, size);
|
||||||
memcpy(blk, src, size);
|
memcpy(blk, src, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::block_t::fill(u32 offset, uint8_t data, u32 size)
|
void fsblk_t::block_t::fill(uint32_t offset, uint8_t data, uint32_t size)
|
||||||
{
|
{
|
||||||
uint8_t *blk = m_object->offset("fill", offset, size);
|
uint8_t *blk = m_object->offset("fill", offset, size);
|
||||||
memset(blk, data, size);
|
memset(blk, data, size);
|
||||||
@ -151,26 +154,26 @@ void fsblk_t::block_t::fill(uint8_t data)
|
|||||||
memset(blk, data, m_object->size());
|
memset(blk, data, m_object->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::block_t::wstr(u32 offset, const std::string &str)
|
void fsblk_t::block_t::wstr(uint32_t offset, const std::string &str)
|
||||||
{
|
{
|
||||||
uint8_t *blk = m_object->offset("wstr", offset, str.size());
|
uint8_t *blk = m_object->offset("wstr", offset, str.size());
|
||||||
memcpy(blk, str.data(), str.size());
|
memcpy(blk, str.data(), str.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::block_t::w8(u32 offset, uint8_t data)
|
void fsblk_t::block_t::w8(uint32_t offset, uint8_t data)
|
||||||
{
|
{
|
||||||
uint8_t *blk = m_object->offset("w8", offset, 1);
|
uint8_t *blk = m_object->offset("w8", offset, 1);
|
||||||
blk[0] = data;
|
blk[0] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::block_t::w16b(u32 offset, u16 data)
|
void fsblk_t::block_t::w16b(uint32_t offset, uint16_t data)
|
||||||
{
|
{
|
||||||
uint8_t *blk = m_object->offset("w16b", offset, 2);
|
uint8_t *blk = m_object->offset("w16b", offset, 2);
|
||||||
blk[0] = data >> 8;
|
blk[0] = data >> 8;
|
||||||
blk[1] = data;
|
blk[1] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::block_t::w24b(u32 offset, u32 data)
|
void fsblk_t::block_t::w24b(uint32_t offset, uint32_t data)
|
||||||
{
|
{
|
||||||
uint8_t *blk = m_object->offset("w24b", offset, 3);
|
uint8_t *blk = m_object->offset("w24b", offset, 3);
|
||||||
blk[0] = data >> 16;
|
blk[0] = data >> 16;
|
||||||
@ -178,7 +181,7 @@ void fsblk_t::block_t::w24b(u32 offset, u32 data)
|
|||||||
blk[2] = data;
|
blk[2] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::block_t::w32b(u32 offset, u32 data)
|
void fsblk_t::block_t::w32b(uint32_t offset, uint32_t data)
|
||||||
{
|
{
|
||||||
uint8_t *blk = m_object->offset("w32b", offset, 4);
|
uint8_t *blk = m_object->offset("w32b", offset, 4);
|
||||||
blk[0] = data >> 24;
|
blk[0] = data >> 24;
|
||||||
@ -187,14 +190,14 @@ void fsblk_t::block_t::w32b(u32 offset, u32 data)
|
|||||||
blk[3] = data;
|
blk[3] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::block_t::w16l(u32 offset, u16 data)
|
void fsblk_t::block_t::w16l(uint32_t offset, uint16_t data)
|
||||||
{
|
{
|
||||||
uint8_t *blk = m_object->offset("w16l", offset, 2);
|
uint8_t *blk = m_object->offset("w16l", offset, 2);
|
||||||
blk[0] = data;
|
blk[0] = data;
|
||||||
blk[1] = data >> 8;
|
blk[1] = data >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::block_t::w24l(u32 offset, u32 data)
|
void fsblk_t::block_t::w24l(uint32_t offset, uint32_t data)
|
||||||
{
|
{
|
||||||
uint8_t *blk = m_object->offset("w24l", offset, 3);
|
uint8_t *blk = m_object->offset("w24l", offset, 3);
|
||||||
blk[0] = data;
|
blk[0] = data;
|
||||||
@ -202,7 +205,7 @@ void fsblk_t::block_t::w24l(u32 offset, u32 data)
|
|||||||
blk[2] = data >> 16;
|
blk[2] = data >> 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::block_t::w32l(u32 offset, u32 data)
|
void fsblk_t::block_t::w32l(uint32_t offset, uint32_t data)
|
||||||
{
|
{
|
||||||
uint8_t *blk = m_object->offset("w32l", offset, 4);
|
uint8_t *blk = m_object->offset("w32l", offset, 4);
|
||||||
blk[0] = data;
|
blk[0] = data;
|
||||||
@ -211,52 +214,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(uint32_t offset, uint32_t size)
|
||||||
{
|
{
|
||||||
const u8 *d = m_object->rooffset("rstr", offset, size);
|
const uint8_t *d = m_object->rooffset("rstr", offset, size);
|
||||||
std::string res;
|
return std::string(d, d + size);
|
||||||
for(u32 i=0; i != size; i++)
|
|
||||||
res += char(*d++);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t fsblk_t::block_t::r8(u32 offset)
|
uint8_t fsblk_t::block_t::r8(uint32_t offset)
|
||||||
{
|
{
|
||||||
const uint8_t *blk = m_object->offset("r8", offset, 1);
|
const uint8_t *blk = m_object->offset("r8", offset, 1);
|
||||||
return blk[0];
|
return blk[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t fsblk_t::block_t::r16b(u32 offset)
|
uint16_t fsblk_t::block_t::r16b(uint32_t offset)
|
||||||
{
|
{
|
||||||
const uint8_t *blk = m_object->offset("r16b", offset, 2);
|
const uint8_t *blk = m_object->offset("r16b", offset, 2);
|
||||||
return (blk[0] << 8) | blk[1];
|
return (blk[0] << 8) | blk[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fsblk_t::block_t::r24b(u32 offset)
|
uint32_t fsblk_t::block_t::r24b(uint32_t offset)
|
||||||
{
|
{
|
||||||
const uint8_t *blk = m_object->offset("r24b", offset, 3);
|
const uint8_t *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];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fsblk_t::block_t::r32b(u32 offset)
|
uint32_t fsblk_t::block_t::r32b(uint32_t offset)
|
||||||
{
|
{
|
||||||
const uint8_t *blk = m_object->offset("r32b", offset, 4);
|
const uint8_t *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];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t fsblk_t::block_t::r16l(u32 offset)
|
uint16_t fsblk_t::block_t::r16l(uint32_t offset)
|
||||||
{
|
{
|
||||||
const uint8_t *blk = m_object->offset("r16l", offset, 2);
|
const uint8_t *blk = m_object->offset("r16l", offset, 2);
|
||||||
return blk[0] | (blk[1] << 8);
|
return blk[0] | (blk[1] << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fsblk_t::block_t::r24l(u32 offset)
|
uint32_t fsblk_t::block_t::r24l(uint32_t offset)
|
||||||
{
|
{
|
||||||
const uint8_t *blk = m_object->offset("r24l", offset, 3);
|
const uint8_t *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);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fsblk_t::block_t::r32l(u32 offset)
|
uint32_t fsblk_t::block_t::r32l(uint32_t offset)
|
||||||
{
|
{
|
||||||
const uint8_t *blk = m_object->offset("r32l", offset, 4);
|
const uint8_t *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);
|
||||||
@ -264,12 +264,12 @@ uint32_t fsblk_t::block_t::r32l(u32 offset)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void filesystem_t::copy(uint8_t *p, const uint8_t *src, u32 size)
|
void filesystem_t::copy(uint8_t *p, const uint8_t *src, uint32_t size)
|
||||||
{
|
{
|
||||||
memcpy(p, src, size);
|
memcpy(p, src, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::fill(uint8_t *p, uint8_t data, u32 size)
|
void filesystem_t::fill(uint8_t *p, uint8_t data, uint32_t size)
|
||||||
{
|
{
|
||||||
memset(p, data, size);
|
memset(p, data, size);
|
||||||
}
|
}
|
||||||
@ -284,20 +284,20 @@ void filesystem_t::w8(uint8_t *p, uint8_t data)
|
|||||||
p[0] = data;
|
p[0] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::w16b(uint8_t *p, u16 data)
|
void filesystem_t::w16b(uint8_t *p, uint16_t data)
|
||||||
{
|
{
|
||||||
p[0] = data >> 8;
|
p[0] = data >> 8;
|
||||||
p[1] = data;
|
p[1] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::w24b(uint8_t *p, u32 data)
|
void filesystem_t::w24b(uint8_t *p, uint32_t data)
|
||||||
{
|
{
|
||||||
p[0] = data >> 16;
|
p[0] = data >> 16;
|
||||||
p[1] = data >> 8;
|
p[1] = data >> 8;
|
||||||
p[2] = data;
|
p[2] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::w32b(uint8_t *p, u32 data)
|
void filesystem_t::w32b(uint8_t *p, uint32_t data)
|
||||||
{
|
{
|
||||||
p[0] = data >> 24;
|
p[0] = data >> 24;
|
||||||
p[1] = data >> 16;
|
p[1] = data >> 16;
|
||||||
@ -305,20 +305,20 @@ void filesystem_t::w32b(uint8_t *p, u32 data)
|
|||||||
p[3] = data;
|
p[3] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::w16l(uint8_t *p, u16 data)
|
void filesystem_t::w16l(uint8_t *p, uint16_t data)
|
||||||
{
|
{
|
||||||
p[0] = data;
|
p[0] = data;
|
||||||
p[1] = data >> 8;
|
p[1] = data >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::w24l(uint8_t *p, u32 data)
|
void filesystem_t::w24l(uint8_t *p, uint32_t data)
|
||||||
{
|
{
|
||||||
p[0] = data;
|
p[0] = data;
|
||||||
p[1] = data >> 8;
|
p[1] = data >> 8;
|
||||||
p[2] = data >> 16;
|
p[2] = data >> 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::w32l(uint8_t *p, u32 data)
|
void filesystem_t::w32l(uint8_t *p, uint32_t data)
|
||||||
{
|
{
|
||||||
p[0] = data;
|
p[0] = data;
|
||||||
p[1] = data >> 8;
|
p[1] = data >> 8;
|
||||||
@ -326,12 +326,9 @@ void filesystem_t::w32l(uint8_t *p, u32 data)
|
|||||||
p[3] = data >> 24;
|
p[3] = data >> 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string filesystem_t::rstr(const uint8_t *p, u32 size)
|
std::string filesystem_t::rstr(const uint8_t *p, uint32_t size)
|
||||||
{
|
{
|
||||||
std::string res;
|
return std::string(p, p + size);
|
||||||
for(u32 i=0; i != size; i++)
|
|
||||||
res += char(*p++);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t filesystem_t::r8(const uint8_t *p)
|
uint8_t filesystem_t::r8(const uint8_t *p)
|
||||||
@ -377,77 +374,41 @@ std::string filesystem_t::trim_end_spaces(const std::string &str)
|
|||||||
|
|
||||||
filesystem_t::file_t filesystem_t::idir_t::file_create(const fs_meta_data &info)
|
filesystem_t::file_t filesystem_t::idir_t::file_create(const fs_meta_data &info)
|
||||||
{
|
{
|
||||||
fatalerror("file_create called on a filesystem not supporting write\n");
|
throw std::logic_error("file_create called on a filesystem not supporting write");
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::idir_t::file_delete(uint64_t key)
|
void filesystem_t::idir_t::file_delete(uint64_t key)
|
||||||
{
|
{
|
||||||
fatalerror("file_delete called on a filesystem not supporting write\n");
|
throw std::logic_error("file_delete called on a filesystem not supporting write");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void filesystem_t::ifile_t::replace(const std::vector<u8> &data)
|
void filesystem_t::ifile_t::replace(const std::vector<uint8_t> &data)
|
||||||
{
|
{
|
||||||
fatalerror("replace called on a filesystem not supporting write \n");
|
throw std::logic_error("replace called on a filesystem not supporting write");
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::ifile_t::rsrc_replace(const std::vector<u8> &data)
|
void filesystem_t::ifile_t::rsrc_replace(const std::vector<uint8_t> &data)
|
||||||
{
|
{
|
||||||
fatalerror("rsrc_replace called on a filesystem not supporting write or resource forks \n");
|
throw std::logic_error("rsrc_replace called on a filesystem not supporting write or resource forks");
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::ifile_t::metadata_change(const fs_meta_data &info)
|
void filesystem_t::ifile_t::metadata_change(const fs_meta_data &info)
|
||||||
{
|
{
|
||||||
fatalerror("metadata_change called on a filesystem not supporting write \n");
|
throw std::logic_error("metadata_change called on a filesystem not supporting write");
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::idir_t::metadata_change(const fs_meta_data &info)
|
void filesystem_t::idir_t::metadata_change(const fs_meta_data &info)
|
||||||
{
|
{
|
||||||
fatalerror("metadata_change called on a filesystem not supporting write \n");
|
throw std::logic_error("metadata_change called on a filesystem not supporting write");
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystem_t::metadata_change(const fs_meta_data &info)
|
void filesystem_t::metadata_change(const fs_meta_data &info)
|
||||||
{
|
{
|
||||||
fatalerror("metadata_change called on a filesystem not supporting write \n");
|
throw std::logic_error("metadata_change called on a filesystem not supporting write");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> filesystem_t::ifile_t::rsrc_read_all()
|
std::vector<uint8_t> filesystem_t::ifile_t::rsrc_read_all()
|
||||||
{
|
{
|
||||||
fatalerror("rsrc_read_all called on a filesystem without resource forks\n");
|
throw std::logic_error("rsrc_read_all called on a filesystem without resource forks");
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *fs_meta_data::entry_name(fs_meta_name name)
|
|
||||||
{
|
|
||||||
switch(name) {
|
|
||||||
case fs_meta_name::basic: return "basic";
|
|
||||||
case fs_meta_name::creation_date: return "creation_date";
|
|
||||||
case fs_meta_name::length: return "length";
|
|
||||||
case fs_meta_name::loading_address: return "loading_address";
|
|
||||||
case fs_meta_name::locked: return "locked";
|
|
||||||
case fs_meta_name::modification_date: return "modification_date";
|
|
||||||
case fs_meta_name::name: return "name";
|
|
||||||
case fs_meta_name::os_minimum_version: return "os_minimum_version";
|
|
||||||
case fs_meta_name::os_version: return "os_version";
|
|
||||||
case fs_meta_name::rsrc_length: return "rsrc_length";
|
|
||||||
case fs_meta_name::sequential: return "sequential";
|
|
||||||
case fs_meta_name::size_in_blocks: return "size_in_blocks";
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string fs_meta::to_string(fs_meta_type type, const fs_meta &m)
|
|
||||||
{
|
|
||||||
switch(type) {
|
|
||||||
case fs_meta_type::string: return m.as_string();
|
|
||||||
case fs_meta_type::number: return util::string_format("0x%x", m.as_number());
|
|
||||||
case fs_meta_type::flag: return m.as_flag() ? "t" : "f";
|
|
||||||
case fs_meta_type::date: {
|
|
||||||
auto dt = m.as_date();
|
|
||||||
return util::string_format("%04d-%02d-%02d %02d:%02d:%02d",
|
|
||||||
dt.year, dt.month, dt.day_of_month,
|
|
||||||
dt.hour, dt.minute, dt.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::string("");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -9,88 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "flopimg.h"
|
#include "flopimg.h"
|
||||||
#include "timeconv.h"
|
#include "fsmeta.h"
|
||||||
|
|
||||||
#include <variant>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
enum class fs_meta_name {
|
|
||||||
basic,
|
|
||||||
creation_date,
|
|
||||||
length,
|
|
||||||
loading_address,
|
|
||||||
locked,
|
|
||||||
modification_date,
|
|
||||||
name,
|
|
||||||
os_minimum_version,
|
|
||||||
os_version,
|
|
||||||
rsrc_length,
|
|
||||||
sequential,
|
|
||||||
size_in_blocks,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class fs_meta_type {
|
|
||||||
date,
|
|
||||||
flag,
|
|
||||||
number,
|
|
||||||
string,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class fs_dir_entry_type {
|
|
||||||
dir,
|
|
||||||
file,
|
|
||||||
system_file,
|
|
||||||
};
|
|
||||||
|
|
||||||
class fs_meta {
|
|
||||||
public:
|
|
||||||
static std::string to_string(fs_meta_type type, const fs_meta &m);
|
|
||||||
static fs_meta from_string(fs_meta_type type, std::string value);
|
|
||||||
|
|
||||||
fs_meta() { value = false; }
|
|
||||||
fs_meta(std::string str) { value = str; }
|
|
||||||
fs_meta(bool b) { value = b; }
|
|
||||||
fs_meta(int32_t num) { value = uint64_t(num); }
|
|
||||||
fs_meta(uint32_t num) { value = uint64_t(num); }
|
|
||||||
fs_meta(int64_t num) { value = uint64_t(num); }
|
|
||||||
fs_meta(uint64_t num) { value = num; }
|
|
||||||
fs_meta(util::arbitrary_datetime dt) { value = dt; }
|
|
||||||
|
|
||||||
util::arbitrary_datetime as_date() const { return *std::get_if<util::arbitrary_datetime>(&value); }
|
|
||||||
bool as_flag() const { return *std::get_if<bool>(&value); }
|
|
||||||
uint64_t as_number() const { return *std::get_if<uint64_t>(&value); }
|
|
||||||
std::string as_string() const { return *std::get_if<std::string>(&value); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::variant<std::string, uint64_t, bool, util::arbitrary_datetime> value;
|
|
||||||
};
|
|
||||||
|
|
||||||
class fs_meta_data {
|
|
||||||
public:
|
|
||||||
std::unordered_map<fs_meta_name, fs_meta> meta;
|
|
||||||
|
|
||||||
static const char *entry_name(fs_meta_name name);
|
|
||||||
|
|
||||||
bool has(fs_meta_name name) const { return meta.find(name) != meta.end(); }
|
|
||||||
bool empty() const { return meta.empty(); }
|
|
||||||
|
|
||||||
void set(fs_meta_name name, const fs_meta &val) { meta[name] = val; }
|
|
||||||
void set(fs_meta_name name, std::string str) { set(name, fs_meta(str)); }
|
|
||||||
void set(fs_meta_name name, bool b) { set(name, fs_meta(b)); }
|
|
||||||
void set(fs_meta_name name, int32_t num) { set(name, fs_meta(num)); }
|
|
||||||
void set(fs_meta_name name, uint32_t num) { set(name, fs_meta(num)); }
|
|
||||||
void set(fs_meta_name name, int64_t num) { set(name, fs_meta(num)); }
|
|
||||||
void set(fs_meta_name name, uint64_t num) { set(name, fs_meta(num)); }
|
|
||||||
void set(fs_meta_name name, util::arbitrary_datetime dt) { set(name, fs_meta(dt)); }
|
|
||||||
void set_now(fs_meta_name name) { set(name, fs_meta(util::arbitrary_datetime::now())); }
|
|
||||||
|
|
||||||
fs_meta get(fs_meta_name name) const { auto i = meta.find(name); if(i == meta.end()) fatalerror("Entry %s not found\n", entry_name(name)); else return i->second; }
|
|
||||||
util::arbitrary_datetime get_date(fs_meta_name name, util::arbitrary_datetime def = util::arbitrary_datetime::now()) const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_date(); }
|
|
||||||
bool get_flag(fs_meta_name name, bool def = false) const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_flag(); }
|
|
||||||
uint64_t get_number(fs_meta_name name, uint64_t def = 0) const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_number(); }
|
|
||||||
std::string get_string(fs_meta_name name, std::string def = "") const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_string(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T> class fs_refcounted_outer {
|
template<typename T> class fs_refcounted_outer {
|
||||||
public:
|
public:
|
||||||
@ -173,23 +92,6 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct fs_meta_description {
|
|
||||||
fs_meta_name m_name;
|
|
||||||
fs_meta_type m_type;
|
|
||||||
fs_meta m_default;
|
|
||||||
bool m_ro;
|
|
||||||
std::function<void (const fs_meta &)> m_validator;
|
|
||||||
const char *m_tooltip;
|
|
||||||
|
|
||||||
fs_meta_description(fs_meta_name name, fs_meta_type type, int def, bool ro, std::function<void (fs_meta)> validator, const char *tooltip) :
|
|
||||||
m_name(name), m_type(type), m_default(uint64_t(def)), m_ro(ro), m_validator(validator), m_tooltip(tooltip)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename T> fs_meta_description(fs_meta_name name, fs_meta_type type, T def, bool ro, std::function<void (fs_meta)> validator, const char *tooltip) :
|
|
||||||
m_name(name), m_type(type), m_default(def), m_ro(ro), m_validator(validator), m_tooltip(tooltip)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
class fs_refcounted_inner {
|
class fs_refcounted_inner {
|
||||||
public:
|
public:
|
||||||
fs_refcounted_inner() : m_ref(0), m_weak_ref(0) {}
|
fs_refcounted_inner() : m_ref(0), m_weak_ref(0) {}
|
||||||
@ -206,6 +108,12 @@ public:
|
|||||||
uint32_t m_ref, m_weak_ref;
|
uint32_t m_ref, m_weak_ref;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class fs_dir_entry_type {
|
||||||
|
dir,
|
||||||
|
file,
|
||||||
|
system_file,
|
||||||
|
};
|
||||||
|
|
||||||
struct fs_dir_entry {
|
struct fs_dir_entry {
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
fs_dir_entry_type m_type;
|
fs_dir_entry_type m_type;
|
||||||
@ -308,10 +216,10 @@ protected:
|
|||||||
|
|
||||||
virtual fs_meta_data metadata() = 0;
|
virtual fs_meta_data metadata() = 0;
|
||||||
virtual void metadata_change(const fs_meta_data &info);
|
virtual void metadata_change(const fs_meta_data &info);
|
||||||
virtual std::vector<u8> read_all() = 0;
|
virtual std::vector<uint8_t> read_all() = 0;
|
||||||
virtual void replace(const std::vector<u8> &data);
|
virtual void replace(const std::vector<uint8_t> &data);
|
||||||
virtual std::vector<u8> rsrc_read_all();
|
virtual std::vector<uint8_t> rsrc_read_all();
|
||||||
virtual void rsrc_replace(const std::vector<u8> &data);
|
virtual void rsrc_replace(const std::vector<uint8_t> &data);
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -344,13 +252,13 @@ public:
|
|||||||
|
|
||||||
fs_meta_data metadata() { return m_object->metadata(); }
|
fs_meta_data metadata() { return m_object->metadata(); }
|
||||||
void metadata_change(const fs_meta_data &info) { m_object->metadata_change(info); }
|
void metadata_change(const fs_meta_data &info) { m_object->metadata_change(info); }
|
||||||
std::vector<u8> read_all() { return m_object->read_all(); }
|
std::vector<uint8_t> read_all() { return m_object->read_all(); }
|
||||||
void replace(const std::vector<u8> &data) { m_object->replace(data); }
|
void replace(const std::vector<uint8_t> &data) { m_object->replace(data); }
|
||||||
std::vector<u8> rsrc_read_all() { return m_object->rsrc_read_all(); }
|
std::vector<uint8_t> rsrc_read_all() { return m_object->rsrc_read_all(); }
|
||||||
void rsrc_replace(const std::vector<u8> &data) { m_object->rsrc_replace(data); }
|
void rsrc_replace(const std::vector<uint8_t> &data) { m_object->rsrc_replace(data); }
|
||||||
};
|
};
|
||||||
|
|
||||||
filesystem_t(fsblk_t &blockdev, u32 size) : m_blockdev(blockdev) {
|
filesystem_t(fsblk_t &blockdev, uint32_t size) : m_blockdev(blockdev) {
|
||||||
m_blockdev.set_block_size(size);
|
m_blockdev.set_block_size(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
#define VERBOSE ( LOG_WARN )
|
#define VERBOSE ( LOG_WARN )
|
||||||
|
|
||||||
#define __EMU_H__ // logmacro wasn't really intended to be used outside stuff that uses libemu
|
#define __EMU_H__ // logmacro wasn't really intended to be used outside stuff that uses libemu
|
||||||
#include "logmacro.h"
|
#include "../emu/logmacro.h"
|
||||||
|
|
||||||
|
|
||||||
// ====================================================
|
// ====================================================
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
|
|
||||||
#include "corestr.h"
|
#include "corestr.h"
|
||||||
#include "ioprocs.h"
|
#include "ioprocs.h"
|
||||||
|
#include "strformat.h"
|
||||||
|
|
||||||
|
#include "osdcomm.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
@ -18,6 +21,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
|
||||||
static formats_table formats;
|
static formats_table formats;
|
||||||
@ -704,7 +708,7 @@ int CLIB_DECL main(int argc, char *argv[])
|
|||||||
display_usage();
|
display_usage();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} catch(const emu_fatalerror &err) {
|
} catch(const std::exception &err) {
|
||||||
fprintf(stderr, "Error: %s", err.what());
|
fprintf(stderr, "Error: %s", err.what());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -12,20 +12,7 @@
|
|||||||
#include "ioprocs.h"
|
#include "ioprocs.h"
|
||||||
#include "ioprocsfill.h"
|
#include "ioprocsfill.h"
|
||||||
#include "ioprocsvec.h"
|
#include "ioprocsvec.h"
|
||||||
|
#include "strformat.h"
|
||||||
|
|
||||||
// Fatalerror implementation
|
|
||||||
|
|
||||||
emu_fatalerror::emu_fatalerror(util::format_argument_pack<std::ostream> const &args)
|
|
||||||
: emu_fatalerror(0, args)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
emu_fatalerror::emu_fatalerror(int _exitcode, util::format_argument_pack<std::ostream> const &args)
|
|
||||||
: m_text(util::string_format(args))
|
|
||||||
, m_code(_exitcode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Format enumeration
|
// Format enumeration
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../emu/emucore.h"
|
|
||||||
|
|
||||||
#include "formats/fsmgr.h"
|
#include "formats/fsmgr.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
Loading…
Reference in New Issue
Block a user