mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
Added Apple 2 disk image format: .nib (read-only support) (#7725)
This format was not supported by the new floppy subsystem. This commit provides read-only support of .nib files.
This commit is contained in:
parent
75a7445a98
commit
3fc703e806
@ -49,11 +49,11 @@ ROM_START( applesurance )
|
||||
ROM_END
|
||||
|
||||
FLOPPY_FORMATS_MEMBER( diskiing_device::floppy_formats )
|
||||
FLOPPY_A216S_FORMAT, FLOPPY_RWTS18_FORMAT, FLOPPY_EDD_FORMAT, FLOPPY_WOZ_FORMAT
|
||||
FLOPPY_A216S_FORMAT, FLOPPY_RWTS18_FORMAT, FLOPPY_EDD_FORMAT, FLOPPY_WOZ_FORMAT, FLOPPY_NIB_FORMAT
|
||||
FLOPPY_FORMATS_END
|
||||
|
||||
FLOPPY_FORMATS_MEMBER( a2bus_diskiing13_device::floppy_formats )
|
||||
FLOPPY_EDD_FORMAT, FLOPPY_WOZ_FORMAT
|
||||
FLOPPY_EDD_FORMAT, FLOPPY_WOZ_FORMAT, FLOPPY_NIB_FORMAT
|
||||
FLOPPY_FORMATS_END
|
||||
|
||||
//-------------------------------------------------
|
||||
|
@ -9,14 +9,16 @@
|
||||
|
||||
FLOPPY_FORMATS_MEMBER(applefdintf_device::formats_525_13)
|
||||
FLOPPY_EDD_FORMAT,
|
||||
FLOPPY_WOZ_FORMAT
|
||||
FLOPPY_WOZ_FORMAT,
|
||||
FLOPPY_NIB_FORMAT
|
||||
FLOPPY_FORMATS_END
|
||||
|
||||
FLOPPY_FORMATS_MEMBER(applefdintf_device::formats_525)
|
||||
FLOPPY_A216S_FORMAT,
|
||||
FLOPPY_RWTS18_FORMAT,
|
||||
FLOPPY_EDD_FORMAT,
|
||||
FLOPPY_WOZ_FORMAT
|
||||
FLOPPY_WOZ_FORMAT,
|
||||
FLOPPY_NIB_FORMAT
|
||||
FLOPPY_FORMATS_END
|
||||
|
||||
FLOPPY_FORMATS_MEMBER(applefdintf_device::formats_35)
|
||||
|
@ -1746,3 +1746,171 @@ uint32_t a2_woz_format::crc32r(const uint8_t *data, uint32_t size)
|
||||
|
||||
|
||||
const floppy_format_type FLOPPY_WOZ_FORMAT = &floppy_image_format_creator<a2_woz_format>;
|
||||
|
||||
|
||||
a2_nib_format::a2_nib_format() : floppy_image_format_t()
|
||||
{
|
||||
}
|
||||
|
||||
const char *a2_nib_format::name() const
|
||||
{
|
||||
return "a2_nib";
|
||||
}
|
||||
|
||||
const char *a2_nib_format::description() const
|
||||
{
|
||||
return "Apple II NIB Image";
|
||||
}
|
||||
|
||||
const char *a2_nib_format::extensions() const
|
||||
{
|
||||
return "nib";
|
||||
}
|
||||
|
||||
bool a2_nib_format::supports_save() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int a2_nib_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
|
||||
{
|
||||
const auto size = io_generic_size(io);
|
||||
if (size == expected_size_35t || size == expected_size_40t) {
|
||||
return 50;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template<class It>
|
||||
static
|
||||
size_t count_leading_FFs(const It first, const It last)
|
||||
{
|
||||
auto curr = first;
|
||||
for (; curr != last; ++curr) {
|
||||
if (*curr != 0xFF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return curr - first;
|
||||
}
|
||||
|
||||
static
|
||||
size_t count_trailing_padding(const std::vector<uint8_t>& nibbles) {
|
||||
const auto b = nibbles.rbegin();
|
||||
const auto e = nibbles.rend();
|
||||
auto i = b;
|
||||
|
||||
// skip until the first valid nibble...
|
||||
for (; i != e; ++i) {
|
||||
if ((*i & 0x80) != 0) { // valid nibble
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i - b;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> a2_nib_format::generate_levels_from_nibbles(const std::vector<uint8_t>& nibbles)
|
||||
{
|
||||
std::vector<uint32_t> levels;
|
||||
const auto append_FFs = [&] (size_t count) {
|
||||
while (count-- > 0) {
|
||||
raw_w(levels, 8, 0xFF);
|
||||
}
|
||||
};
|
||||
const auto append_syncs = [&] (size_t count) {
|
||||
while (count-- > 0) {
|
||||
raw_w(levels, 10, 0x00FF << 2);
|
||||
}
|
||||
};
|
||||
const auto append_byte = [&] (uint8_t byte) {
|
||||
raw_w(levels, 8, byte);
|
||||
};
|
||||
|
||||
|
||||
const auto leading_FF_count =
|
||||
count_leading_FFs(nibbles.begin(), nibbles.end());
|
||||
|
||||
if (leading_FF_count >= nibbles.size()) { // all are 0xFF !?!?
|
||||
assert(leading_FF_count >= min_sync_bytes);
|
||||
append_syncs(leading_FF_count);
|
||||
return levels;
|
||||
}
|
||||
|
||||
const auto trailing_padding_size = count_trailing_padding(nibbles);
|
||||
const auto trailing_FF_count =
|
||||
count_leading_FFs(nibbles.rbegin() + trailing_padding_size,
|
||||
nibbles.rend());
|
||||
const auto wrapped_FF_count = leading_FF_count + trailing_FF_count;
|
||||
const bool wrapped_FF_are_syncs = wrapped_FF_count >= min_sync_bytes;
|
||||
|
||||
if (wrapped_FF_are_syncs) {
|
||||
append_syncs(leading_FF_count);
|
||||
} else {
|
||||
append_FFs(leading_FF_count);
|
||||
}
|
||||
|
||||
{
|
||||
size_t FF_count = 0;
|
||||
const auto flush_FFs = [&] {
|
||||
if (FF_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (FF_count >= a2_nib_format::min_sync_bytes) {
|
||||
append_syncs(FF_count);
|
||||
} else {
|
||||
append_FFs(FF_count);
|
||||
}
|
||||
FF_count = 0;
|
||||
};
|
||||
|
||||
const auto end = nibbles.end() - trailing_padding_size - trailing_FF_count;
|
||||
for (auto i = nibbles.begin() + leading_FF_count; i != end; ++i) {
|
||||
const auto nibble = *i;
|
||||
if ((nibble & 0x80) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nibble == 0xFF) {
|
||||
++FF_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
flush_FFs();
|
||||
append_byte(nibble);
|
||||
}
|
||||
flush_FFs();
|
||||
}
|
||||
|
||||
if (wrapped_FF_are_syncs) {
|
||||
append_syncs(trailing_FF_count);
|
||||
} else {
|
||||
append_FFs(trailing_FF_count);
|
||||
}
|
||||
|
||||
return levels;
|
||||
}
|
||||
|
||||
bool a2_nib_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
|
||||
{
|
||||
auto size = io_generic_size(io);
|
||||
if (size != expected_size_35t && size != expected_size_40t) {
|
||||
return false;
|
||||
}
|
||||
const auto nr_tracks = size == expected_size_35t? 35 : 40;
|
||||
|
||||
std::vector<uint8_t> nibbles(nibbles_per_track);
|
||||
for (unsigned track = 0; track < nr_tracks; ++track) {
|
||||
io_generic_read(io, &nibbles[0],
|
||||
track * nibbles_per_track, nibbles_per_track);
|
||||
auto levels = generate_levels_from_nibbles(nibbles);
|
||||
generate_track_from_levels(track, 0,
|
||||
levels,
|
||||
0, image);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const floppy_format_type FLOPPY_NIB_FORMAT = &floppy_image_format_creator<a2_nib_format>;
|
||||
|
@ -132,4 +132,30 @@ private:
|
||||
|
||||
extern const floppy_format_type FLOPPY_WOZ_FORMAT;
|
||||
|
||||
|
||||
class a2_nib_format : public floppy_image_format_t
|
||||
{
|
||||
public:
|
||||
a2_nib_format();
|
||||
|
||||
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 supports_save() const override;
|
||||
|
||||
virtual const char *name() const override;
|
||||
virtual const char *description() const override;
|
||||
virtual const char *extensions() const override;
|
||||
|
||||
|
||||
private:
|
||||
static constexpr size_t nibbles_per_track = 0x1a00;
|
||||
static constexpr size_t min_sync_bytes = 4;
|
||||
static constexpr auto expected_size_35t = 35 * nibbles_per_track;
|
||||
static constexpr auto expected_size_40t = 40 * nibbles_per_track;
|
||||
|
||||
std::vector<uint32_t> generate_levels_from_nibbles(const std::vector<uint8_t>& nibbles);
|
||||
};
|
||||
|
||||
extern const floppy_format_type FLOPPY_NIB_FORMAT;
|
||||
|
||||
#endif // MAME_FORMATS_AP2_DSK_H
|
||||
|
@ -55,7 +55,7 @@ static void a3_floppies(device_slot_interface &device)
|
||||
}
|
||||
|
||||
FLOPPY_FORMATS_MEMBER( apple3_state::floppy_formats )
|
||||
FLOPPY_A216S_FORMAT, FLOPPY_RWTS18_FORMAT, FLOPPY_EDD_FORMAT, FLOPPY_WOZ_FORMAT
|
||||
FLOPPY_A216S_FORMAT, FLOPPY_RWTS18_FORMAT, FLOPPY_EDD_FORMAT, FLOPPY_WOZ_FORMAT, FLOPPY_NIB_FORMAT
|
||||
FLOPPY_FORMATS_END
|
||||
|
||||
void apple3_state::apple3(machine_config &config)
|
||||
|
@ -94,6 +94,7 @@ static floppy_format_type floppy_formats[] = {
|
||||
FLOPPY_RWTS18_FORMAT,
|
||||
FLOPPY_EDD_FORMAT,
|
||||
FLOPPY_WOZ_FORMAT,
|
||||
FLOPPY_NIB_FORMAT,
|
||||
|
||||
FLOPPY_ATOM_FORMAT,
|
||||
FLOPPY_ACORN_SSD_FORMAT,
|
||||
|
Loading…
Reference in New Issue
Block a user