diff --git a/src/devices/bus/a2bus/a2diskiing.cpp b/src/devices/bus/a2bus/a2diskiing.cpp index 45d792c761c..3a41fe04890 100644 --- a/src/devices/bus/a2bus/a2diskiing.cpp +++ b/src/devices/bus/a2bus/a2diskiing.cpp @@ -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 //------------------------------------------------- diff --git a/src/devices/machine/applefdintf.cpp b/src/devices/machine/applefdintf.cpp index e21c33230eb..b579d254d36 100755 --- a/src/devices/machine/applefdintf.cpp +++ b/src/devices/machine/applefdintf.cpp @@ -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) diff --git a/src/lib/formats/ap2_dsk.cpp b/src/lib/formats/ap2_dsk.cpp index 374ecc4a060..1a2e2a65e68 100644 --- a/src/lib/formats/ap2_dsk.cpp +++ b/src/lib/formats/ap2_dsk.cpp @@ -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_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 &variants) +{ + const auto size = io_generic_size(io); + if (size == expected_size_35t || size == expected_size_40t) { + return 50; + } + return 0; +} + + +template +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& 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 a2_nib_format::generate_levels_from_nibbles(const std::vector& nibbles) +{ + std::vector 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 &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 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; diff --git a/src/lib/formats/ap2_dsk.h b/src/lib/formats/ap2_dsk.h index a12994f3755..15b41503ce9 100644 --- a/src/lib/formats/ap2_dsk.h +++ b/src/lib/formats/ap2_dsk.h @@ -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 &variants) override; + virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &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 generate_levels_from_nibbles(const std::vector& nibbles); +}; + +extern const floppy_format_type FLOPPY_NIB_FORMAT; + #endif // MAME_FORMATS_AP2_DSK_H diff --git a/src/mame/drivers/apple3.cpp b/src/mame/drivers/apple3.cpp index 470825e3a36..9f4687380ee 100644 --- a/src/mame/drivers/apple3.cpp +++ b/src/mame/drivers/apple3.cpp @@ -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) diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp index ca847736510..1beb4304860 100644 --- a/src/tools/floptool.cpp +++ b/src/tools/floptool.cpp @@ -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,