summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author leesaudan2 <leesaudan2@users.noreply.github.com>2021-01-31 02:35:58 +0800
committer GitHub <noreply@github.com>2021-01-30 19:35:58 +0100
commit3fc703e80694f421cf873f566d0ee66f8765a8ec (patch)
tree629db2225ef6ebd5fe2de8cd7196777943dbb24d
parent75a7445a985a9d90780566966db4ade4e2229019 (diff)
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.
-rw-r--r--src/devices/bus/a2bus/a2diskiing.cpp4
-rwxr-xr-xsrc/devices/machine/applefdintf.cpp6
-rw-r--r--src/lib/formats/ap2_dsk.cpp168
-rw-r--r--src/lib/formats/ap2_dsk.h26
-rw-r--r--src/mame/drivers/apple3.cpp2
-rw-r--r--src/tools/floptool.cpp1
6 files changed, 202 insertions, 5 deletions
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_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>;
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<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
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,