mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
floppy: start block-devicing fielsystem support
This commit is contained in:
parent
3b24032ba8
commit
8709e06b67
@ -72,6 +72,8 @@ project "formats"
|
||||
|
||||
MAME_DIR .. "src/lib/formats/fsmgr.h",
|
||||
MAME_DIR .. "src/lib/formats/fsmgr.cpp",
|
||||
MAME_DIR .. "src/lib/formats/fsblk_vec.h",
|
||||
MAME_DIR .. "src/lib/formats/fsblk_vec.cpp",
|
||||
MAME_DIR .. "src/lib/formats/fs_unformatted.h",
|
||||
MAME_DIR .. "src/lib/formats/fs_unformatted.cpp",
|
||||
}
|
||||
@ -2069,4 +2071,16 @@ if opt_tool(FORMATS, "FS_PRODOS") then
|
||||
}
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
--
|
||||
--@src/lib/formats/fs_oric_jasmin.h,FORMATS["FS_ORIC_JASMIN"] = true
|
||||
--------------------------------------------------
|
||||
|
||||
if opt_tool(FORMATS, "FS_ORIC_JASMIN") then
|
||||
files {
|
||||
MAME_DIR.. "src/lib/formats/fs_oric_jasmin.cpp",
|
||||
MAME_DIR.. "src/lib/formats/fs_oric_jasmin.h",
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "emu.h"
|
||||
#include "jasmin.h"
|
||||
#include "formats/oric_dsk.h"
|
||||
#include "formats/fs_oric_jasmin.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(ORIC_JASMIN, oric_jasmin_device, "oric_jasmin", "Jasmin floppy drive interface")
|
||||
|
||||
@ -15,6 +16,9 @@ void oric_jasmin_device::floppy_formats(format_registration &fr)
|
||||
{
|
||||
fr.add_mfm_containers();
|
||||
fr.add(FLOPPY_ORIC_DSK_FORMAT);
|
||||
fr.add(FLOPPY_ORIC_JASMIN_FORMAT);
|
||||
|
||||
fr.add(FS_ORIC_JASMIN);
|
||||
}
|
||||
|
||||
static void jasmin_floppies(device_slot_interface &device)
|
||||
@ -24,7 +28,7 @@ static void jasmin_floppies(device_slot_interface &device)
|
||||
|
||||
INPUT_PORTS_START( jasmin )
|
||||
PORT_START("JASMIN")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Boot") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CHANGED_MEMBER(DEVICE_SELF, oric_jasmin_device, boot_pressed, 0)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Boot") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CHANGED_MEMBER(DEVICE_SELF, oric_jasmin_device, boot_pressed, 0)
|
||||
INPUT_PORTS_END
|
||||
|
||||
void oric_jasmin_device::map(address_map &map)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "formats/pc_dsk.h"
|
||||
|
||||
#include "formats/fs_unformatted.h"
|
||||
#include "formats/fsblk_vec.h"
|
||||
|
||||
#include "speaker.h"
|
||||
#include "formats/imageutl.h"
|
||||
@ -308,14 +309,17 @@ void floppy_image_device::setup_led_cb(led_cb cb)
|
||||
cur_led_cb = cb;
|
||||
}
|
||||
|
||||
void floppy_image_device::fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description)
|
||||
void floppy_image_device::fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description)
|
||||
{
|
||||
m_fid->m_fs.emplace_back(fs_info(manager, type, image_size, name, key, description));
|
||||
if(manager->can_format())
|
||||
m_fid->m_create_fs.emplace_back(fs_info(manager, type, image_size, name, description));
|
||||
if(manager->can_read())
|
||||
m_fid->m_io_fs.emplace_back(fs_info(manager, type, image_size, name, description));
|
||||
}
|
||||
|
||||
void floppy_image_device::fs_enum::add_raw(const filesystem_manager_t *manager, const char *name, u32 key, const char *description)
|
||||
void floppy_image_device::fs_enum::add_raw(const char *name, u32 key, const char *description)
|
||||
{
|
||||
m_fid->m_fs.emplace_back(fs_info(manager, name, key, description));
|
||||
m_fid->m_create_fs.emplace_back(fs_info(name, key, description));
|
||||
}
|
||||
|
||||
void floppy_image_device::register_formats()
|
||||
@ -718,14 +722,17 @@ void floppy_image_device::init_fs(const fs_info *fs)
|
||||
if (fs->m_type)
|
||||
{
|
||||
std::vector<u8> img(fs->m_image_size);
|
||||
fs->m_manager->floppy_instantiate(fs->m_key, img);
|
||||
fsblk_vec_t blockdev(img);
|
||||
auto cfs = fs->m_manager->mount(blockdev);
|
||||
cfs->format();
|
||||
|
||||
auto iog = ram_open(img);
|
||||
auto source_format = fs->m_type();
|
||||
source_format->load(iog, floppy_image::FF_UNKNOWN, variants, image.get());
|
||||
delete source_format;
|
||||
delete iog;
|
||||
} else
|
||||
fs->m_manager->floppy_instantiate_raw(fs->m_key, image.get());
|
||||
fs_unformatted::format(fs->m_key, image.get());
|
||||
}
|
||||
|
||||
/* write protect, active high
|
||||
|
@ -56,17 +56,17 @@ public:
|
||||
u32 m_key;
|
||||
const char *m_description;
|
||||
|
||||
fs_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) :
|
||||
fs_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) :
|
||||
m_manager(manager),
|
||||
m_type(type),
|
||||
m_image_size(image_size),
|
||||
m_name(name),
|
||||
m_key(key),
|
||||
m_key(0),
|
||||
m_description(description)
|
||||
{}
|
||||
|
||||
fs_info(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) :
|
||||
m_manager(manager),
|
||||
fs_info(const char *name, u32 key, const char *description) :
|
||||
m_manager(nullptr),
|
||||
m_type(nullptr),
|
||||
m_image_size(0),
|
||||
m_name(name),
|
||||
@ -80,7 +80,8 @@ public:
|
||||
|
||||
void set_formats(std::function<void (format_registration &fr)> formats);
|
||||
floppy_image_format_t *get_formats() const;
|
||||
const std::vector<fs_info> &get_fs() const { return m_fs; }
|
||||
const std::vector<fs_info> &get_create_fs() const { return m_create_fs; }
|
||||
const std::vector<fs_info> &get_io_fs() const { return m_io_fs; }
|
||||
floppy_image_format_t *get_load_format() const;
|
||||
floppy_image_format_t *identify(std::string filename);
|
||||
void set_rpm(float rpm);
|
||||
@ -158,8 +159,8 @@ protected:
|
||||
floppy_image_device *m_fid;
|
||||
fs_enum(floppy_image_device *fid) : filesystem_manager_t::floppy_enumerator(), m_fid(fid) {};
|
||||
|
||||
virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) override;
|
||||
virtual void add_raw(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) override;
|
||||
virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) override;
|
||||
virtual void add_raw(const char *name, u32 key, const char *description) override;
|
||||
};
|
||||
|
||||
floppy_image_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
@ -186,7 +187,7 @@ protected:
|
||||
std::unique_ptr<floppy_image> image;
|
||||
char extension_list[256];
|
||||
floppy_image_format_t *fif_list;
|
||||
std::vector<fs_info> m_fs;
|
||||
std::vector<fs_info> m_create_fs, m_io_fs;
|
||||
std::vector<std::unique_ptr<filesystem_manager_t>> m_fs_managers;
|
||||
emu_timer *index_timer;
|
||||
|
||||
|
@ -129,7 +129,7 @@ void menu_control_floppy_image::handle()
|
||||
m_state = START_FILE;
|
||||
handle();
|
||||
} else {
|
||||
const auto &fs = fd.get_fs();
|
||||
const auto &fs = fd.get_create_fs();
|
||||
output_filename = util::zippath_combine(m_current_directory, m_current_file);
|
||||
output_format = format_array[m_submenu_result.i];
|
||||
if(fs.size() == 1) {
|
||||
@ -149,7 +149,7 @@ void menu_control_floppy_image::handle()
|
||||
m_state = START_FILE;
|
||||
handle();
|
||||
} else {
|
||||
create_fs = &fd.get_fs()[m_submenu_result.i];
|
||||
create_fs = &fd.get_create_fs()[m_submenu_result.i];
|
||||
do_load_create();
|
||||
stack_pop();
|
||||
}
|
||||
|
@ -457,6 +457,10 @@
|
||||
#include "oric_tap.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAS_FORMATS_FS_ORIC_JASMIN
|
||||
#include "fs_oric_jasmin.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAS_FORMATS_IBMXDF_DSK
|
||||
#include "ibmxdf_dsk.h"
|
||||
#endif
|
||||
@ -1130,6 +1134,10 @@ void mame_formats_full_list(mame_formats_enumerator &en)
|
||||
#endif
|
||||
#ifdef HAS_FORMATS_ORIC_DSK
|
||||
en.add(FLOPPY_ORIC_DSK_FORMAT); // oric_dsk.h
|
||||
en.add(FLOPPY_ORIC_JASMIN_FORMAT); // oric_dsk.h
|
||||
#endif
|
||||
#ifdef HAS_FORMATS_FS_ORIC_JASMIN
|
||||
en.add(FS_ORIC_JASMIN); // fs_oric_jasmin.h
|
||||
#endif
|
||||
|
||||
en.category("Atari");
|
||||
|
@ -936,6 +936,9 @@ void floppy_image::get_actual_geometry(int &_tracks, int &_heads)
|
||||
goto head_done;
|
||||
maxh--;
|
||||
}
|
||||
else
|
||||
maxh = -1;
|
||||
|
||||
head_done:
|
||||
_tracks = (maxt+4)/4;
|
||||
_heads = maxh+1;
|
||||
|
113
src/lib/formats/fs_oric_jasmin.cpp
Normal file
113
src/lib/formats/fs_oric_jasmin.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// Creation of Apple Oric_Jasmin floppy images
|
||||
|
||||
#include "emu.h"
|
||||
#include "fs_oric_jasmin.h"
|
||||
#include "oric_dsk.h"
|
||||
|
||||
// Floppy only, format is 41 tracks, 1/2 heads, 17 sectors.
|
||||
// Filesystem has no subdirectories.
|
||||
//
|
||||
// References are pair of bytes (track + head*41, sector)
|
||||
//
|
||||
// Track 20 sector 1 has the free bitmap and the volume name
|
||||
//
|
||||
// offset 3*(track + head*41): bitmap from track, 24 bits LSB first,
|
||||
// sector 1 in bit 16, sector 17 in bit 0.
|
||||
// 0x01ffff is empty track. Special value
|
||||
// 0x800000 marks a full track.
|
||||
// offset f6-f7: 0x8080
|
||||
// offset f8-ff: volume name, padded with 0x20
|
||||
//
|
||||
//
|
||||
// Track 20 sector 2 has the first directory sector.
|
||||
// Directory sector format:
|
||||
// offset 00-01: reference to the sector, (0, 0) for the first one
|
||||
// offset 02-03: reference to the next sector, (0, 0) on the first sector if it's the end, (ff, 00) for the end of another sector
|
||||
// offset 04+ : 14 file entries, 18 bytes each
|
||||
// offset 00-01: reference to the first sector of the inode, (ff, xx) when no entry
|
||||
// offset 02 : U/L for (U)nlocked or (L)ocked file
|
||||
// offset 03-0e: filename.ext, space padiing between filename and '.'
|
||||
// offset 0f : S/D for (S)equential (normal) or (D)irect-access files
|
||||
// offset 10-11: number of sectors used by the file, including inode, little-endian
|
||||
//
|
||||
// Inodes:
|
||||
// offset 00-01: reference to the next inode sector, (ff, 00) on the last one
|
||||
// offset 02-03: loading address for the file on the first sector, ffff otherwise
|
||||
// offset 04-05: length of the file in bytes on the first sector, ffff otherwise
|
||||
// offset 06+ : reference to data sectors, (ff, ff) when done
|
||||
|
||||
void fs_oric_jasmin::enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const
|
||||
{
|
||||
if(has(form_factor, variants, floppy_image::FF_3, floppy_image::DSDD))
|
||||
fe.add(this, FLOPPY_ORIC_JASMIN_FORMAT, 356864, "oric_jasmin_ds", "Oric Jasmin dual-sided");
|
||||
if(has(form_factor, variants, floppy_image::FF_3, floppy_image::SSDD))
|
||||
fe.add(this, FLOPPY_ORIC_JASMIN_FORMAT, 178432, "oric_jasmin_ss", "Oric Jasmin single-sided");
|
||||
}
|
||||
|
||||
std::unique_ptr<filesystem_t> fs_oric_jasmin::mount(fsblk_t &blockdev) const
|
||||
{
|
||||
return std::make_unique<impl>(blockdev);
|
||||
}
|
||||
|
||||
bool fs_oric_jasmin::can_format() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fs_oric_jasmin::can_read() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fs_oric_jasmin::can_write() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void fs_oric_jasmin::impl::format()
|
||||
{
|
||||
std::string volume_name = "UNTITLED";
|
||||
m_blockdev.set_block_size(256);
|
||||
u32 blocks = m_blockdev.block_count();
|
||||
|
||||
m_blockdev.fill(0x6c);
|
||||
|
||||
u32 bblk = 20*17;
|
||||
auto fmap = m_blockdev.get(bblk);
|
||||
u32 off = 0;
|
||||
for(u32 blk = 0; blk != blocks; blk += 17) {
|
||||
if(blk == bblk) {
|
||||
fmap.w8(off , 0xff);
|
||||
fmap.w8(off + 1, 0x7f);
|
||||
fmap.w8(off + 2, 0x00);
|
||||
} else {
|
||||
fmap.w8(off , 0xff);
|
||||
fmap.w8(off + 1, 0xff);
|
||||
fmap.w8(off + 2, 0x01);
|
||||
}
|
||||
off += 3;
|
||||
}
|
||||
|
||||
for(u32 blk = blocks; blk != 17*42*2; blk += 17) {
|
||||
fmap.w8(off , 0x00);
|
||||
fmap.w8(off + 1, 0x00);
|
||||
fmap.w8(off + 2, 0x80);
|
||||
off += 3;
|
||||
}
|
||||
|
||||
fmap.w8(0xf6, 0x80);
|
||||
fmap.w8(0xf7, 0x80);
|
||||
fmap.fill(0xf8, 0x20, 8);
|
||||
fmap.wstr(0xf8, volume_name);
|
||||
|
||||
auto bdir = m_blockdev.get(20*17+1);
|
||||
bdir.fill(0xff);
|
||||
bdir.w16l(0, 0x0000);
|
||||
bdir.w16l(2, 0x0000);
|
||||
}
|
||||
|
||||
const filesystem_manager_type FS_ORIC_JASMIN = &filesystem_manager_creator<fs_oric_jasmin>;;
|
35
src/lib/formats/fs_oric_jasmin.h
Normal file
35
src/lib/formats/fs_oric_jasmin.h
Normal file
@ -0,0 +1,35 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// Creation of Oric Jasmin floppy images
|
||||
|
||||
#ifndef MAME_FORMATS_FS_ORIC_JASMIN_H
|
||||
#define MAME_FORMATS_FS_ORIC_JASMIN_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fsmgr.h"
|
||||
|
||||
class fs_oric_jasmin : public filesystem_manager_t {
|
||||
public:
|
||||
class impl : public filesystem_t {
|
||||
public:
|
||||
impl(fsblk_t &blockdev) : filesystem_t(blockdev) {}
|
||||
virtual ~impl() = default;
|
||||
|
||||
virtual void format() override;
|
||||
};
|
||||
|
||||
fs_oric_jasmin() : filesystem_manager_t() {}
|
||||
|
||||
virtual void enumerate(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 bool can_format() const override;
|
||||
virtual bool can_read() const override;
|
||||
virtual bool can_write() const override;
|
||||
};
|
||||
|
||||
extern const filesystem_manager_type FS_ORIC_JASMIN;
|
||||
|
||||
#endif
|
@ -7,7 +7,7 @@
|
||||
#include "fs_prodos.h"
|
||||
#include "ap_dsk35.h"
|
||||
|
||||
const u8 fs_prodos::boot[512] = {
|
||||
const u8 fs_prodos::impl::boot[512] = {
|
||||
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,
|
||||
0xd0, 0x3a, 0xb0, 0x0e, 0xa9, 0x03, 0x8d, 0x00, 0x08, 0xe6, 0x3d, 0xa5, 0x49, 0x48, 0xa9, 0x5b,
|
||||
@ -44,49 +44,74 @@ const u8 fs_prodos::boot[512] = {
|
||||
|
||||
void fs_prodos::enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const
|
||||
{
|
||||
bool all = form_factor == floppy_image::FF_UNKNOWN;
|
||||
|
||||
if(all || (form_factor == floppy_image::FF_35 && has_variant(variants, floppy_image::DSDD)))
|
||||
fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 819200, "prodos_800k", 800, "Apple ProDOS 800K");
|
||||
if(all || (form_factor == floppy_image::FF_35 && has_variant(variants, floppy_image::SSDD)))
|
||||
fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 409600, "prodos_400k", 400, "Apple ProDOS 400K");
|
||||
if(has(form_factor, variants, floppy_image::FF_35, floppy_image::DSDD))
|
||||
fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 819200, "prodos_800k", "Apple ProDOS 800K");
|
||||
if(has(form_factor, variants, floppy_image::FF_35, floppy_image::SSDD))
|
||||
fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 409600, "prodos_400k", "Apple ProDOS 400K");
|
||||
}
|
||||
|
||||
void fs_prodos::floppy_instantiate(u32 key, std::vector<u8> &image) const
|
||||
std::unique_ptr<filesystem_t> fs_prodos::mount(fsblk_t &blockdev) const
|
||||
{
|
||||
return std::make_unique<impl>(blockdev);
|
||||
}
|
||||
|
||||
bool fs_prodos::can_format() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fs_prodos::can_read() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fs_prodos::can_write() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void fs_prodos::impl::format()
|
||||
{
|
||||
std::string volume_name = "UNTITLED";
|
||||
u32 blocks = key * 2;
|
||||
m_blockdev.set_block_size(512);
|
||||
u32 blocks = m_blockdev.block_count();
|
||||
|
||||
copy(image, 0x000, boot, 0x200); // Standard ProDOS boot sector as written by a 2gs
|
||||
m_blockdev.get(0).copy(0x000, boot, 0x200); // Standard ProDOS boot sector as written by a 2gs
|
||||
m_blockdev.get(1).fill(0x00); // No SOS boot sector
|
||||
|
||||
fill(image, 0x200, 0x00, 0x200); // No SOS boot sector
|
||||
auto kblk1 = m_blockdev.get(2); // key block first block
|
||||
auto kblk2 = m_blockdev.get(3); // key block second block
|
||||
auto kblk3 = m_blockdev.get(4); // key block third block
|
||||
auto kblk4 = m_blockdev.get(5); // key block fourth block
|
||||
|
||||
w16l(image, 0x400, 0x0000); // Backwards key block pointer (null)
|
||||
w16l(image, 0x402, 0x0003); // Forwards key block pointer
|
||||
w8 (image, 0x404, 0xf0 | volume_name.size()); // Block type (f, key block) and name size
|
||||
wstr(image, 0x405, volume_name); // Volume name, up to 15 characters
|
||||
w32b(image, 0x416, 0x642a250d); // ??? date & time
|
||||
w16b(image, 0x41a, 0x80ff); // ???
|
||||
w32b(image, 0x41c, 0x642a250d); // Creation date & time
|
||||
w8 (image, 0x420, 0x05); // ProDOS version (2gs)
|
||||
w8 (image, 0x421, 0x00); // ProDOS minimum version
|
||||
w8 (image, 0x422, 0xc3); // Allowed access (destroy, rename, !backup, 3x0, write read)
|
||||
w8 (image, 0x423, 0x27); // Directory entry length (fixed)
|
||||
w8 (image, 0x424, 0x0d); // Entries per block (fixed)
|
||||
w16l(image, 0x425, 0x0000); // Number of file entries in the directory
|
||||
w16l(image, 0x427, 0x0006); // Bitmap block pointer
|
||||
w16l(image, 0x429, blocks); // Number of blocks
|
||||
kblk1.w16l(0x00, 0x0000); // Backwards key block pointer (null)
|
||||
kblk1.w16l(0x02, 0x0003); // Forwards key block pointer
|
||||
kblk1.w8 (0x04, 0xf0 | volume_name.size()); // Block type (f, key block) and name size
|
||||
kblk1.wstr(0x05, volume_name); // Volume name, up to 15 characters
|
||||
kblk1.w32b(0x16, 0x642a250d); // ??? date & time
|
||||
kblk1.w16b(0x1a, 0x80ff); // ???
|
||||
kblk1.w32b(0x1c, 0x642a250d); // Creation date & time
|
||||
kblk1.w8 (0x20, 0x05); // ProDOS version (2gs)
|
||||
kblk1.w8 (0x21, 0x00); // ProDOS minimum version
|
||||
kblk1.w8 (0x22, 0xc3); // Allowed access (destroy, rename, !backup, 3x0, write read)
|
||||
kblk1.w8 (0x23, 0x27); // Directory entry length (fixed)
|
||||
kblk1.w8 (0x24, 0x0d); // Entries per block (fixed)
|
||||
kblk1.w16l(0x25, 0x0000); // Number of file entries in the directory
|
||||
kblk1.w16l(0x27, 0x0006); // Bitmap block pointer
|
||||
kblk1.w16l(0x29, blocks); // Number of blocks
|
||||
|
||||
w16l(image, 0x600, 0x0002); // Backwards block pointer of the second volume block
|
||||
w16l(image, 0x602, 0x0004); // Forwards block pointer of the second volume block
|
||||
w16l(image, 0x800, 0x0003); // Backwards block pointer of the third volume block
|
||||
w16l(image, 0x802, 0x0005); // Forwards block pointer of the third volume block
|
||||
w16l(image, 0xa00, 0x0004); // Backwards block pointer of the fourth volume block
|
||||
w16l(image, 0xa02, 0x0000); // Forwards block pointer of the fourth volume block (nmull)
|
||||
kblk2.w16l(0x00, 0x0002); // Backwards block pointer of the second volume block
|
||||
kblk2.w16l(0x02, 0x0004); // Forwards block pointer of the second volume block
|
||||
kblk3.w16l(0x00, 0x0003); // Backwards block pointer of the third volume block
|
||||
kblk3.w16l(0x02, 0x0005); // Forwards block pointer of the third 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)
|
||||
|
||||
auto fmap = m_blockdev.get(6);
|
||||
u8 *fdata = fmap.data();
|
||||
// Mark blocks 7 to max as free
|
||||
for(u32 i = 7; i != blocks; i++)
|
||||
image[0xc00 + (i >> 3)] |= 0x80 >> (i & 7);
|
||||
fdata[i >> 3] |= 0x80 >> (i & 7);
|
||||
}
|
||||
|
||||
const filesystem_manager_type FS_PRODOS = &filesystem_manager_creator<fs_prodos>;;
|
||||
|
@ -12,13 +12,25 @@
|
||||
|
||||
class fs_prodos : public filesystem_manager_t {
|
||||
public:
|
||||
class impl : public filesystem_t {
|
||||
public:
|
||||
impl(fsblk_t &blockdev) : filesystem_t(blockdev) {}
|
||||
virtual ~impl() = default;
|
||||
|
||||
virtual void format() override;
|
||||
|
||||
private:
|
||||
static const u8 boot[512];
|
||||
};
|
||||
|
||||
fs_prodos() : filesystem_manager_t() {}
|
||||
|
||||
virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
|
||||
virtual void floppy_instantiate(u32 key, std::vector<u8> &image) const override;
|
||||
virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override;
|
||||
|
||||
private:
|
||||
static const u8 boot[512];
|
||||
virtual bool can_format() const override;
|
||||
virtual bool can_read() const override;
|
||||
virtual bool can_write() const override;
|
||||
};
|
||||
|
||||
extern const filesystem_manager_type FS_PRODOS;
|
||||
|
@ -35,43 +35,43 @@ void fs_unformatted::enumerate(floppy_enumerator &fe, uint32_t form_factor, cons
|
||||
: FSI_NONE;
|
||||
|
||||
if(all || best_8 == FSI_8_DSDD)
|
||||
fe.add_raw(this, "u8dsdd", FSI_8_DSDD, "Unformatted 8\" double-sided double-density");
|
||||
fe.add_raw("u8dsdd", FSI_8_DSDD, "Unformatted 8\" double-sided double-density");
|
||||
if(all || best_8 == FSI_8_DSSD)
|
||||
fe.add_raw(this, "u8dssd", FSI_8_DSSD, "Unformatted 8\" double-sided single-density");
|
||||
fe.add_raw("u8dssd", FSI_8_DSSD, "Unformatted 8\" double-sided single-density");
|
||||
if(all || best_8 == FSI_8_SSSD)
|
||||
fe.add_raw(this, "u8sssd", FSI_8_SSSD, "Unformatted 8\" single-sided single-density");
|
||||
fe.add_raw("u8sssd", FSI_8_SSSD, "Unformatted 8\" single-sided single-density");
|
||||
|
||||
if(all || best_525 == FSI_525_DSHD)
|
||||
fe.add_raw(this, "u525dshd", FSI_525_DSHD, "Unformatted 5\"25 double-sided high-density");
|
||||
fe.add_raw("u525dshd", FSI_525_DSHD, "Unformatted 5\"25 double-sided high-density");
|
||||
if(all || best_525 == FSI_525_DSQD)
|
||||
fe.add_raw(this, "u525dsqd", FSI_525_DSQD, "Unformatted 5\"25 double-sided quad-density");
|
||||
fe.add_raw("u525dsqd", FSI_525_DSQD, "Unformatted 5\"25 double-sided quad-density");
|
||||
if(all || best_525 == FSI_525_DSDD)
|
||||
fe.add_raw(this, "u525dsdd", FSI_525_DSDD, "Unformatted 5\"25 double-sided double-density");
|
||||
fe.add_raw("u525dsdd", FSI_525_DSDD, "Unformatted 5\"25 double-sided double-density");
|
||||
if(all)
|
||||
fe.add_raw(this, "u525dssd", FSI_525_DSSD, "Unformatted 5\"25 double-sided single-density");
|
||||
fe.add_raw("u525dssd", FSI_525_DSSD, "Unformatted 5\"25 double-sided single-density");
|
||||
if(all || best_525 == FSI_525_SSQD)
|
||||
fe.add_raw(this, "u525ssqd", FSI_525_SSQD, "Unformatted 5\"25 single-sided quad-density");
|
||||
fe.add_raw("u525ssqd", FSI_525_SSQD, "Unformatted 5\"25 single-sided quad-density");
|
||||
if(all || best_525 == FSI_525_SSDD)
|
||||
fe.add_raw(this, "u525ssdd", FSI_525_SSDD, "Unformatted 5\"25 single-sided double-density");
|
||||
fe.add_raw("u525ssdd", FSI_525_SSDD, "Unformatted 5\"25 single-sided double-density");
|
||||
if(all || best_525 == FSI_525_SSSD)
|
||||
fe.add_raw(this, "u525sssd", FSI_525_SSSD, "Unformatted 5\"25 single-sided single-density");
|
||||
fe.add_raw("u525sssd", FSI_525_SSSD, "Unformatted 5\"25 single-sided single-density");
|
||||
|
||||
if(all || has_variant(variants, floppy_image::DSED))
|
||||
fe.add_raw(this, "u35dsed", FSI_35_DSED, "Unformatted 3\"5 double-sided extra-density");
|
||||
fe.add_raw("u35dsed", FSI_35_DSED, "Unformatted 3\"5 double-sided extra-density");
|
||||
if(all || has_variant(variants, floppy_image::DSHD))
|
||||
fe.add_raw(this, "u35dshd", FSI_35_DSHD, "Unformatted 3\"5 double-sided high-density");
|
||||
fe.add_raw("u35dshd", FSI_35_DSHD, "Unformatted 3\"5 double-sided high-density");
|
||||
if(all || best_35 == FSI_35_DSDD)
|
||||
fe.add_raw(this, "u35dsdd", FSI_35_DSDD, "Unformatted 3\"5 double-sided double-density");
|
||||
fe.add_raw("u35dsdd", FSI_35_DSDD, "Unformatted 3\"5 double-sided double-density");
|
||||
if(all || best_35 == FSI_35_SSDD)
|
||||
fe.add_raw(this, "u35ssdd", FSI_35_SSDD, "Unformatted 3\"5 single-sided double-density");
|
||||
fe.add_raw("u35ssdd", FSI_35_SSDD, "Unformatted 3\"5 single-sided double-density");
|
||||
|
||||
if(all || best_3 == FSI_3_DSDD)
|
||||
fe.add_raw(this, "u3dsdd", FSI_35_DSDD, "Unformatted 3\" double-sided double-density");
|
||||
fe.add_raw("u3dsdd", FSI_35_DSDD, "Unformatted 3\" double-sided double-density");
|
||||
if(all || best_3 == FSI_3_SSDD)
|
||||
fe.add_raw(this, "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::floppy_instantiate_raw(u32 key, floppy_image *image) const
|
||||
void fs_unformatted::format(u32 key, floppy_image *image)
|
||||
{
|
||||
switch(key) {
|
||||
case FSI_8_DSDD: image->set_form_variant(floppy_image::FF_8, floppy_image::DSDD); break;
|
||||
@ -96,4 +96,24 @@ void fs_unformatted::floppy_instantiate_raw(u32 key, floppy_image *image) const
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<filesystem_t> fs_unformatted::mount(fsblk_t &blockdev) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool fs_unformatted::can_format() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fs_unformatted::can_read() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fs_unformatted::can_write() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const filesystem_manager_type FS_UNFORMATTED = &filesystem_manager_creator<fs_unformatted>;
|
||||
|
@ -12,12 +12,6 @@
|
||||
|
||||
class fs_unformatted : public filesystem_manager_t {
|
||||
public:
|
||||
fs_unformatted() : filesystem_manager_t() {}
|
||||
|
||||
virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
|
||||
virtual void floppy_instantiate_raw(u32 key, floppy_image *image) const override;
|
||||
|
||||
private:
|
||||
enum {
|
||||
FSI_NONE,
|
||||
|
||||
@ -41,6 +35,17 @@ private:
|
||||
FSI_3_DSDD,
|
||||
FSI_3_SSDD,
|
||||
};
|
||||
|
||||
fs_unformatted() : filesystem_manager_t() {}
|
||||
|
||||
static void format(u32 key, floppy_image *image);
|
||||
|
||||
virtual void enumerate(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 bool can_format() const override;
|
||||
virtual bool can_read() const override;
|
||||
virtual bool can_write() const override;
|
||||
};
|
||||
|
||||
extern const filesystem_manager_type FS_UNFORMATTED;
|
||||
|
39
src/lib/formats/fsblk_vec.cpp
Normal file
39
src/lib/formats/fsblk_vec.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// Block device on vector<uint8_t>
|
||||
|
||||
#include "emu.h"
|
||||
#include "fsblk_vec.h"
|
||||
|
||||
const uint8_t *fsblk_vec_t::blk_t::rodata()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
uint8_t *fsblk_vec_t::blk_t::data()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void fsblk_vec_t::blk_t::drop_weak_references()
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t fsblk_vec_t::block_count() const
|
||||
{
|
||||
return m_data.size() / m_block_size;
|
||||
}
|
||||
|
||||
fsblk_t::block_t fsblk_vec_t::get(uint32_t id)
|
||||
{
|
||||
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);
|
||||
return block_t(new blk_t(m_data.data() + m_block_size*id, m_block_size));
|
||||
}
|
||||
|
||||
void fsblk_vec_t::fill(uint8_t data)
|
||||
{
|
||||
std::fill(m_data.begin(), m_data.end(), data);
|
||||
}
|
||||
|
33
src/lib/formats/fsblk_vec.h
Normal file
33
src/lib/formats/fsblk_vec.h
Normal file
@ -0,0 +1,33 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// Block device on vector<uint8_t>
|
||||
|
||||
#include "fsmgr.h"
|
||||
|
||||
class fsblk_vec_t : public fsblk_t {
|
||||
private:
|
||||
class blk_t : public iblock_t {
|
||||
public:
|
||||
blk_t(uint8_t *data, uint32_t size) : iblock_t(size), m_data(data) {}
|
||||
virtual ~blk_t() = default;
|
||||
|
||||
virtual const uint8_t *rodata() override;
|
||||
virtual uint8_t *data() override;
|
||||
virtual void drop_weak_references() override;
|
||||
|
||||
private:
|
||||
uint8_t *m_data;
|
||||
};
|
||||
|
||||
public:
|
||||
fsblk_vec_t(std::vector<uint8_t> &data) : m_data(data) {}
|
||||
virtual ~fsblk_vec_t() = default;
|
||||
|
||||
virtual uint32_t block_count() const override;
|
||||
virtual block_t get(uint32_t id) override;
|
||||
virtual void fill(uint8_t data) override;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> &m_data;
|
||||
};
|
@ -8,20 +8,47 @@
|
||||
#include "emu.h"
|
||||
#include "fsmgr.h"
|
||||
|
||||
void fsblk_t::iblock_t::ref()
|
||||
{
|
||||
m_ref ++;
|
||||
}
|
||||
|
||||
void fsblk_t::iblock_t::ref_weak()
|
||||
{
|
||||
m_weak_ref ++;
|
||||
}
|
||||
|
||||
void fsblk_t::iblock_t::unref()
|
||||
{
|
||||
m_ref --;
|
||||
if(m_ref == 0) {
|
||||
if(m_weak_ref) {
|
||||
drop_weak_references();
|
||||
if(m_weak_ref)
|
||||
fatalerror("drop_weak_references kept %d active references\n", m_weak_ref);
|
||||
} else
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void fsblk_t::iblock_t::unref_weak()
|
||||
{
|
||||
m_weak_ref --;
|
||||
if(m_weak_ref == 0 && m_ref == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
void filesystem_manager_t::enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const
|
||||
{
|
||||
}
|
||||
|
||||
void filesystem_manager_t::floppy_instantiate(u32 key, std::vector<u8> &image) const
|
||||
void filesystem_manager_t::enumerate(hd_enumerator &he) const
|
||||
{
|
||||
fprintf(stderr, "filesystem_manager_t::floppy_instantiate called while unsupported\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
void filesystem_manager_t::floppy_instantiate_raw(u32 key, floppy_image *image) const
|
||||
void filesystem_manager_t::enumerate(cdrom_enumerator &ce) const
|
||||
{
|
||||
fprintf(stderr, "filesystem_manager_t::floppy_instantiate_raw called while unsupported\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
bool filesystem_manager_t::has_variant(const std::vector<uint32_t> &variants, uint32_t variant)
|
||||
@ -32,50 +59,99 @@ bool filesystem_manager_t::has_variant(const std::vector<uint32_t> &variants, ui
|
||||
return false;
|
||||
}
|
||||
|
||||
void filesystem_manager_t::copy(std::vector<u8> &image, u32 offset, const u8 *src, u32 size)
|
||||
bool filesystem_manager_t::has(uint32_t form_factor, const std::vector<uint32_t> &variants, uint32_t ff, uint32_t variant)
|
||||
{
|
||||
memcpy(image.data() + offset, src, size);
|
||||
if(form_factor == floppy_image::FF_UNKNOWN)
|
||||
return true;
|
||||
if(form_factor != ff)
|
||||
return false;
|
||||
for(uint32_t v : variants)
|
||||
if(variant == v)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void filesystem_manager_t::fill(std::vector<u8> &image, u32 offset, u8 data, u32 size)
|
||||
void filesystem_t::format()
|
||||
{
|
||||
memset(image.data() + offset, data, size);
|
||||
fatalerror("format called on filesystem not supporting it.\n");
|
||||
}
|
||||
|
||||
void filesystem_manager_t::wstr(std::vector<u8> &image, u32 offset, const std::string &str)
|
||||
filesystem_t::dir_t filesystem_t::root()
|
||||
{
|
||||
memcpy(image.data() + offset, str.data(), str.size());
|
||||
fatalerror("root called on filesystem not supporting it.\n");
|
||||
}
|
||||
|
||||
void filesystem_manager_t::w8(std::vector<u8> &image, u32 offset, u8 data)
|
||||
void fsblk_t::set_block_size(uint32_t block_size)
|
||||
{
|
||||
image[offset] = data;
|
||||
m_block_size = block_size;
|
||||
}
|
||||
|
||||
void filesystem_manager_t::w16b(std::vector<u8> &image, u32 offset, u16 data)
|
||||
|
||||
uint8_t *fsblk_t::iblock_t::offset(const char *function, uint32_t off, uint32_t size)
|
||||
{
|
||||
image[offset ] = data >> 8;
|
||||
image[offset+1] = data;
|
||||
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);
|
||||
return data() + off;
|
||||
}
|
||||
|
||||
void filesystem_manager_t::w32b(std::vector<u8> &image, u32 offset, u32 data)
|
||||
void fsblk_t::block_t::copy(u32 offset, const uint8_t *src, u32 size)
|
||||
{
|
||||
image[offset ] = data >> 24;
|
||||
image[offset+1] = data >> 16;
|
||||
image[offset+2] = data >> 8;
|
||||
image[offset+3] = data;
|
||||
uint8_t *blk = m_block->offset("copy", offset, size);
|
||||
memcpy(blk, src, size);
|
||||
}
|
||||
|
||||
void filesystem_manager_t::w16l(std::vector<u8> &image, u32 offset, u16 data)
|
||||
void fsblk_t::block_t::fill(u32 offset, uint8_t data, u32 size)
|
||||
{
|
||||
image[offset ] = data;
|
||||
image[offset+1] = data >> 8;
|
||||
uint8_t *blk = m_block->offset("fill", offset, size);
|
||||
memset(blk, data, size);
|
||||
}
|
||||
|
||||
void filesystem_manager_t::w32l(std::vector<u8> &image, u32 offset, u32 data)
|
||||
void fsblk_t::block_t::fill(uint8_t data)
|
||||
{
|
||||
image[offset ] = data;
|
||||
image[offset+1] = data >> 8;
|
||||
image[offset+2] = data >> 16;
|
||||
image[offset+3] = data >> 24;
|
||||
uint8_t *blk = m_block->data();
|
||||
memset(blk, data, m_block->size());
|
||||
}
|
||||
|
||||
void fsblk_t::block_t::wstr(u32 offset, const std::string &str)
|
||||
{
|
||||
uint8_t *blk = m_block->offset("wstr", offset, str.size());
|
||||
memcpy(blk, str.data(), str.size());
|
||||
}
|
||||
|
||||
void fsblk_t::block_t::w8(u32 offset, uint8_t data)
|
||||
{
|
||||
uint8_t *blk = m_block->offset("w8", offset, 1);
|
||||
blk[0] = data;
|
||||
}
|
||||
|
||||
void fsblk_t::block_t::w16b(u32 offset, u16 data)
|
||||
{
|
||||
uint8_t *blk = m_block->offset("w16b", offset, 2);
|
||||
blk[0] = data >> 8;
|
||||
blk[1] = data;
|
||||
}
|
||||
|
||||
void fsblk_t::block_t::w32b(u32 offset, u32 data)
|
||||
{
|
||||
uint8_t *blk = m_block->offset("w32b", offset, 4);
|
||||
blk[0] = data >> 24;
|
||||
blk[1] = data >> 16;
|
||||
blk[2] = data >> 8;
|
||||
blk[3] = data;
|
||||
}
|
||||
|
||||
void fsblk_t::block_t::w16l(u32 offset, u16 data)
|
||||
{
|
||||
uint8_t *blk = m_block->offset("w16l", offset, 2);
|
||||
blk[0] = data;
|
||||
blk[1] = data >> 8;
|
||||
}
|
||||
|
||||
void fsblk_t::block_t::w32l(u32 offset, u32 data)
|
||||
{
|
||||
uint8_t *blk = m_block->offset("w32l", offset, 4);
|
||||
blk[0] = data;
|
||||
blk[1] = data >> 8;
|
||||
blk[2] = data >> 16;
|
||||
blk[3] = data >> 24;
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// Filesystem management code for floppy and hd images
|
||||
|
||||
// Currently limited to floppies and creation of preformatted images
|
||||
// Filesystem management code for floppy, hd and cdrom images
|
||||
|
||||
#ifndef MAME_FORMATS_FSMGR_H
|
||||
#define MAME_FORMATS_FSMGR_H
|
||||
@ -12,38 +10,322 @@
|
||||
|
||||
#include "flopimg.h"
|
||||
|
||||
class fsblk_t {
|
||||
protected:
|
||||
class iblock_t {
|
||||
public:
|
||||
iblock_t(uint32_t size) : m_ref(0), m_weak_ref(0), m_size(size) {}
|
||||
virtual ~iblock_t() = default;
|
||||
|
||||
void ref();
|
||||
void ref_weak();
|
||||
void unref();
|
||||
void unref_weak();
|
||||
|
||||
uint32_t size() const { return m_size; }
|
||||
|
||||
virtual void drop_weak_references() = 0;
|
||||
|
||||
virtual const uint8_t *rodata() = 0;
|
||||
virtual uint8_t *data() = 0;
|
||||
uint8_t *offset(const char *function, uint32_t off, uint32_t size);
|
||||
|
||||
protected:
|
||||
uint32_t m_ref, m_weak_ref;
|
||||
uint32_t m_size;
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
class block_t {
|
||||
public:
|
||||
block_t(iblock_t *block, bool weak = false) : m_block(block), m_is_weak_ref(weak) {
|
||||
ref();
|
||||
}
|
||||
|
||||
block_t(const block_t &cref) {
|
||||
m_block = cref.m_block;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
ref();
|
||||
}
|
||||
|
||||
block_t(block_t &&cref) {
|
||||
m_block = cref.m_block;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
cref.m_block = nullptr;
|
||||
}
|
||||
|
||||
~block_t() {
|
||||
unref();
|
||||
}
|
||||
|
||||
block_t &operator =(const block_t &cref) {
|
||||
m_block = cref.m_block;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
block_t &operator =(block_t &&cref) {
|
||||
m_block = cref.m_block;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
cref.m_block = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const uint8_t *rodata() {
|
||||
return m_block ? m_block->rodata() : nullptr;
|
||||
}
|
||||
|
||||
uint8_t *data() {
|
||||
return m_block ? m_block->data() : nullptr;
|
||||
}
|
||||
|
||||
void copy(uint32_t offset, const uint8_t *src, uint32_t size);
|
||||
void fill( uint8_t data);
|
||||
void fill(uint32_t offset, uint8_t data, uint32_t size);
|
||||
void wstr(uint32_t offset, const std::string &str);
|
||||
void w8( uint32_t offset, uint8_t data);
|
||||
void w16b(uint32_t offset, u16 data);
|
||||
void w32b(uint32_t offset, uint32_t data);
|
||||
void w16l(uint32_t offset, u16 data);
|
||||
void w32l(uint32_t offset, uint32_t data);
|
||||
|
||||
private:
|
||||
iblock_t *m_block;
|
||||
bool m_is_weak_ref;
|
||||
|
||||
void ref() {
|
||||
if(m_block) {
|
||||
if(m_is_weak_ref)
|
||||
m_block->ref_weak();
|
||||
else
|
||||
m_block->ref();
|
||||
}
|
||||
}
|
||||
|
||||
void unref() {
|
||||
if(m_block) {
|
||||
if(m_is_weak_ref)
|
||||
m_block->unref_weak();
|
||||
else
|
||||
m_block->unref();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fsblk_t() = default;
|
||||
virtual ~fsblk_t() = default;
|
||||
|
||||
virtual void set_block_size(uint32_t block_size);
|
||||
virtual uint32_t block_count() const = 0;
|
||||
virtual block_t get(uint32_t id) = 0;
|
||||
virtual void fill(uint8_t data) = 0;
|
||||
|
||||
protected:
|
||||
uint32_t m_block_size;
|
||||
};
|
||||
|
||||
|
||||
class filesystem_t {
|
||||
protected:
|
||||
class idir_t {
|
||||
public:
|
||||
virtual ~idir_t();
|
||||
|
||||
void ref();
|
||||
void ref_weak();
|
||||
void unref();
|
||||
void unref_weak();
|
||||
|
||||
virtual void drop_weak_references();
|
||||
};
|
||||
|
||||
class ifile_t {
|
||||
public:
|
||||
virtual ~ifile_t();
|
||||
|
||||
void ref();
|
||||
void ref_weak();
|
||||
void unref();
|
||||
void unref_weak();
|
||||
|
||||
virtual void drop_weak_references();
|
||||
};
|
||||
|
||||
public:
|
||||
class dir_t {
|
||||
public:
|
||||
dir_t(idir_t *dir, bool weak = false) : m_dir(dir), m_is_weak_ref(weak) {
|
||||
ref();
|
||||
}
|
||||
|
||||
dir_t(const dir_t &cref) {
|
||||
m_dir = cref.m_dir;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
ref();
|
||||
}
|
||||
|
||||
dir_t(dir_t &&cref) {
|
||||
m_dir = cref.m_dir;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
cref.m_dir = nullptr;
|
||||
}
|
||||
|
||||
~dir_t() {
|
||||
unref();
|
||||
}
|
||||
|
||||
dir_t &operator =(const dir_t &cref) {
|
||||
m_dir = cref.m_dir;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
dir_t &operator =(dir_t &&cref) {
|
||||
m_dir = cref.m_dir;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
cref.m_dir = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
idir_t *m_dir;
|
||||
bool m_is_weak_ref;
|
||||
|
||||
void ref() {
|
||||
if(m_dir) {
|
||||
if(m_is_weak_ref)
|
||||
m_dir->ref_weak();
|
||||
else
|
||||
m_dir->ref();
|
||||
}
|
||||
}
|
||||
|
||||
void unref() {
|
||||
if(m_dir) {
|
||||
if(m_is_weak_ref)
|
||||
m_dir->unref_weak();
|
||||
else
|
||||
m_dir->unref();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class file_t {
|
||||
public:
|
||||
file_t(ifile_t *file, bool weak = false) : m_file(file), m_is_weak_ref(weak) {
|
||||
ref();
|
||||
}
|
||||
|
||||
file_t(const file_t &cref) {
|
||||
m_file = cref.m_file;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
ref();
|
||||
}
|
||||
|
||||
file_t(file_t &&cref) {
|
||||
m_file = cref.m_file;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
cref.m_file = nullptr;
|
||||
}
|
||||
|
||||
~file_t() {
|
||||
unref();
|
||||
}
|
||||
|
||||
file_t &operator =(const file_t &cref) {
|
||||
m_file = cref.m_file;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
file_t &operator =(file_t &&cref) {
|
||||
m_file = cref.m_file;
|
||||
m_is_weak_ref = cref.m_is_weak_ref;
|
||||
cref.m_file = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
ifile_t *m_file;
|
||||
bool m_is_weak_ref;
|
||||
|
||||
void ref() {
|
||||
if(m_file) {
|
||||
if(m_is_weak_ref)
|
||||
m_file->ref_weak();
|
||||
else
|
||||
m_file->ref();
|
||||
}
|
||||
}
|
||||
|
||||
void unref() {
|
||||
if(m_file) {
|
||||
if(m_is_weak_ref)
|
||||
m_file->unref_weak();
|
||||
else
|
||||
m_file->unref();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
filesystem_t(fsblk_t &blockdev) : m_blockdev(blockdev) {}
|
||||
|
||||
virtual ~filesystem_t() = default;
|
||||
|
||||
virtual void format();
|
||||
virtual dir_t root();
|
||||
|
||||
|
||||
protected:
|
||||
fsblk_t &m_blockdev;
|
||||
};
|
||||
|
||||
class unformatted_floppy_creator;
|
||||
|
||||
class filesystem_manager_t {
|
||||
public:
|
||||
struct floppy_enumerator {
|
||||
virtual ~floppy_enumerator() = default;
|
||||
|
||||
virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) = 0;
|
||||
virtual void add_raw(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) = 0;
|
||||
virtual void add(const filesystem_manager_t *manager, floppy_format_type type, uint32_t image_size, const char *name, const char *description) = 0;
|
||||
virtual void add_raw(const char *name, uint32_t key, const char *description) = 0;
|
||||
};
|
||||
|
||||
struct hd_enumerator {
|
||||
virtual ~hd_enumerator() = default;
|
||||
|
||||
virtual void add(const filesystem_manager_t *manager, const char *name, const char *description) = 0;
|
||||
};
|
||||
|
||||
struct cdrom_enumerator {
|
||||
virtual ~cdrom_enumerator() = default;
|
||||
|
||||
virtual void add(const filesystem_manager_t *manager, const char *name, const char *description) = 0;
|
||||
};
|
||||
|
||||
|
||||
virtual ~filesystem_manager_t() = default;
|
||||
|
||||
virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const;
|
||||
virtual void enumerate(hd_enumerator &he) const;
|
||||
virtual void enumerate(cdrom_enumerator &ce) const;
|
||||
|
||||
// Floppy image initialization
|
||||
virtual void floppy_instantiate(u32 key, std::vector<u8> &image) const;
|
||||
virtual bool can_format() const = 0;
|
||||
virtual bool can_read() const = 0;
|
||||
virtual bool can_write() const = 0;
|
||||
|
||||
// Floppy image initialization for add_raw
|
||||
virtual void floppy_instantiate_raw(u32 key, floppy_image *image) const;
|
||||
// Create a filesystem object from a block device
|
||||
virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const = 0;
|
||||
|
||||
protected:
|
||||
filesystem_manager_t() = default;
|
||||
|
||||
static bool has(uint32_t form_factor, const std::vector<uint32_t> &variants, uint32_t ff, uint32_t variant);
|
||||
static bool has_variant(const std::vector<uint32_t> &variants, uint32_t variant);
|
||||
|
||||
static void copy(std::vector<u8> &image, u32 offset, const u8 *src, u32 size);
|
||||
static void fill(std::vector<u8> &image, u32 offset, u8 data, u32 size);
|
||||
static void wstr(std::vector<u8> &image, u32 offset, const std::string &str);
|
||||
static void w8(std::vector<u8> &image, u32 offset, u8 data);
|
||||
static void w16b(std::vector<u8> &image, u32 offset, u16 data);
|
||||
static void w32b(std::vector<u8> &image, u32 offset, u32 data);
|
||||
static void w16l(std::vector<u8> &image, u32 offset, u16 data);
|
||||
static void w32l(std::vector<u8> &image, u32 offset, u32 data);
|
||||
};
|
||||
|
||||
|
||||
|
@ -11,10 +11,6 @@
|
||||
#include "formats/oric_dsk.h"
|
||||
|
||||
|
||||
oric_dsk_format::oric_dsk_format()
|
||||
{
|
||||
}
|
||||
|
||||
const char *oric_dsk_format::name() const
|
||||
{
|
||||
return "oric_dsk";
|
||||
@ -109,3 +105,97 @@ bool oric_dsk_format::save(io_generic *io, const std::vector<uint32_t> &variants
|
||||
}
|
||||
|
||||
const floppy_format_type FLOPPY_ORIC_DSK_FORMAT = &floppy_image_format_creator<oric_dsk_format>;
|
||||
|
||||
|
||||
const char *oric_jasmin_format::name() const
|
||||
{
|
||||
return "oric_jasmin";
|
||||
}
|
||||
|
||||
const char *oric_jasmin_format::description() const
|
||||
{
|
||||
return "Oric Jasmin pure sector image";
|
||||
}
|
||||
|
||||
const char *oric_jasmin_format::extensions() const
|
||||
{
|
||||
return "dsk";
|
||||
}
|
||||
|
||||
bool oric_jasmin_format::supports_save() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int oric_jasmin_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
|
||||
{
|
||||
int size = io_generic_size(io);
|
||||
bool can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD);
|
||||
if(size == 41*17*256 || (can_ds && size == 41*17*256*2))
|
||||
return 50;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool oric_jasmin_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
|
||||
{
|
||||
int size = io_generic_size(io);
|
||||
bool can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD);
|
||||
|
||||
if(size != 41*17*256 && (!can_ds || size != 41*17*256*2))
|
||||
return false;
|
||||
|
||||
int heads = size == 41*17*256 ? 1 : 2;
|
||||
|
||||
std::vector<uint8_t> data(size);
|
||||
io_generic_read(io, data.data(), 0, size);
|
||||
|
||||
for(int head = 0; head != heads; head++)
|
||||
for(int track = 0; track != 41; track++) {
|
||||
desc_pc_sector sdesc[17];
|
||||
for(int s = 0; s != 17; s++) {
|
||||
int sector = (s + 6*(track+1)) % 17;
|
||||
sdesc[s].track = track;
|
||||
sdesc[s].head = head;
|
||||
sdesc[s].sector = sector + 1;
|
||||
sdesc[s].size = 1;
|
||||
sdesc[s].actual_size = 256;
|
||||
sdesc[s].data = data.data() + 256 * (sector + track*17 + head*17*41);
|
||||
sdesc[s].deleted = false;
|
||||
sdesc[s].bad_crc = false;
|
||||
}
|
||||
|
||||
build_wd_track_mfm(track, head, image, 100000, 17, sdesc, 38, 40);
|
||||
}
|
||||
|
||||
image->set_form_variant(floppy_image::FF_3, heads == 2 ? floppy_image::DSDD : floppy_image::SSDD);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool oric_jasmin_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
|
||||
{
|
||||
int tracks, heads;
|
||||
image->get_actual_geometry(tracks, heads);
|
||||
|
||||
bool can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD);
|
||||
if(heads == 2 && !can_ds)
|
||||
return false;
|
||||
if(heads == 0)
|
||||
heads = 1;
|
||||
|
||||
uint8_t zero[256];
|
||||
memset(zero, 0, 256);
|
||||
|
||||
for(int head = 0; head != heads; head++)
|
||||
for(int track = 0; track != 41; track++) {
|
||||
auto sectors = extract_sectors_from_bitstream_mfm_pc(generate_bitstream_from_track(track, head, 2000, image));
|
||||
for(unsigned int sector = 0; sector != 17; sector ++) {
|
||||
const uint8_t *data = sector+1 < sectors.size() && !sectors[sector+1].empty() ? sectors[sector+1].data() : zero;
|
||||
io_generic_write(io, data, 256 * (sector + track*17 + head*17*41), 256);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const floppy_format_type FLOPPY_ORIC_JASMIN_FORMAT = &floppy_image_format_creator<oric_jasmin_format>;
|
||||
|
@ -17,7 +17,7 @@
|
||||
class oric_dsk_format : public floppy_image_format_t
|
||||
{
|
||||
public:
|
||||
oric_dsk_format();
|
||||
oric_dsk_format() = default;
|
||||
virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
|
||||
virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
|
||||
virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
|
||||
@ -30,4 +30,21 @@ public:
|
||||
|
||||
extern const floppy_format_type FLOPPY_ORIC_DSK_FORMAT;
|
||||
|
||||
class oric_jasmin_format : public floppy_image_format_t
|
||||
{
|
||||
public:
|
||||
oric_jasmin_format() = default;
|
||||
|
||||
virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
|
||||
virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
|
||||
virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
|
||||
|
||||
virtual const char *name() const override;
|
||||
virtual const char *description() const override;
|
||||
virtual const char *extensions() const override;
|
||||
virtual bool supports_save() const override;
|
||||
};
|
||||
|
||||
extern const floppy_format_type FLOPPY_ORIC_JASMIN_FORMAT;
|
||||
|
||||
#endif // MAME_FORMATS_ORIC_DSK_H
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
|
||||
#include "../emu/emucore.h"
|
||||
#include "corestr.h"
|
||||
#include "osdcomm.h"
|
||||
|
||||
@ -27,6 +28,19 @@ using u16 = uint16_t;
|
||||
using u32 = uint32_t;
|
||||
|
||||
#include "formats/all.h"
|
||||
#include "formats/fs_unformatted.h"
|
||||
#include "formats/fsblk_vec.h"
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
struct fs_info {
|
||||
const filesystem_manager_t *m_manager;
|
||||
@ -36,17 +50,17 @@ struct fs_info {
|
||||
u32 m_key;
|
||||
const char *m_description;
|
||||
|
||||
fs_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) :
|
||||
fs_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) :
|
||||
m_manager(manager),
|
||||
m_type(type),
|
||||
m_image_size(image_size),
|
||||
m_name(name),
|
||||
m_key(key),
|
||||
m_key(0),
|
||||
m_description(description)
|
||||
{}
|
||||
|
||||
fs_info(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) :
|
||||
m_manager(manager),
|
||||
fs_info(const char *name, u32 key, const char *description) :
|
||||
m_manager(nullptr),
|
||||
m_type(nullptr),
|
||||
m_image_size(0),
|
||||
m_name(name),
|
||||
@ -133,8 +147,8 @@ struct fs_enum : public filesystem_manager_t::floppy_enumerator {
|
||||
fs_enum(enumerator *en) : filesystem_manager_t::floppy_enumerator(), m_en(en) {};
|
||||
|
||||
void reg(const fs_info &fsi) const;
|
||||
virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description) override;
|
||||
virtual void add_raw(const filesystem_manager_t *manager, const char *name, u32 key, const char *description) override;
|
||||
virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) override;
|
||||
virtual void add_raw(const char *name, u32 key, const char *description) override;
|
||||
};
|
||||
|
||||
struct enumerator : public mame_formats_enumerator {
|
||||
@ -193,15 +207,15 @@ void fs_enum::reg(const fs_info &fsi) const
|
||||
fs_by_key.emplace(key, fsi);
|
||||
}
|
||||
|
||||
void fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, u32 key, const char *description)
|
||||
void fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description)
|
||||
{
|
||||
fs_info fsi(manager, type, image_size, name, key, description);
|
||||
fs_info fsi(manager, type, image_size, name, description);
|
||||
reg(fsi);
|
||||
}
|
||||
|
||||
void fs_enum::add_raw(const filesystem_manager_t *manager, const char *name, u32 key, const char *description)
|
||||
void fs_enum::add_raw(const char *name, u32 key, const char *description)
|
||||
{
|
||||
fs_info fsi(manager, name, key, description);
|
||||
fs_info fsi(name, key, description);
|
||||
reg(fsi);
|
||||
}
|
||||
|
||||
@ -280,7 +294,7 @@ static void display_formats()
|
||||
if(!e.second.empty()) {
|
||||
fprintf(stderr, "%s:\n", e.first.c_str());
|
||||
for(floppy_image_format_t *fif : e.second)
|
||||
fprintf(stderr, " %-*s - %s [%s]\n", sk, fif->name(), fif->description(), fif->extensions());
|
||||
fprintf(stderr, " %-*s - %s [%s]\n", sk, fif->name(), fif->description(), fif->extensions());
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n\n");
|
||||
@ -289,7 +303,13 @@ static void display_formats()
|
||||
if(!e.second.empty()) {
|
||||
fprintf(stderr, "%s:\n", e.first.c_str());
|
||||
for(const fs_info &fs : e.second)
|
||||
fprintf(stderr, " %-*s - %s\n", sk, fs.m_name, fs.m_description);
|
||||
fprintf(stderr, " %-*s %c%c%c - %s\n",
|
||||
sk,
|
||||
fs.m_name,
|
||||
!fs.m_manager || fs.m_manager->can_format() ? 'f' : '-',
|
||||
fs.m_manager && fs.m_manager->can_read() ? 'r' : '-',
|
||||
fs.m_manager && fs.m_manager->can_write() ? 'w' : '-',
|
||||
fs.m_description);
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,7 +455,10 @@ static int create(int argc, char *argv[])
|
||||
|
||||
if(source_fs->m_type) {
|
||||
std::vector<u8> img(source_fs->m_image_size);
|
||||
source_fs->m_manager->floppy_instantiate(source_fs->m_key, img);
|
||||
fsblk_vec_t blockdev(img);
|
||||
auto fs = source_fs->m_manager->mount(blockdev);
|
||||
fs->format();
|
||||
|
||||
auto iog = ram_open(img);
|
||||
auto source_format = source_fs->m_type();
|
||||
source_format->load(iog, floppy_image::FF_UNKNOWN, variants, &image);
|
||||
@ -443,7 +466,7 @@ static int create(int argc, char *argv[])
|
||||
delete iog;
|
||||
|
||||
} else
|
||||
source_fs->m_manager->floppy_instantiate_raw(source_fs->m_key, &image);
|
||||
fs_unformatted::format(source_fs->m_key, &image);
|
||||
|
||||
char msg[4096];
|
||||
sprintf(msg, "Error opening %s for writing", argv[4]);
|
||||
|
Loading…
Reference in New Issue
Block a user