From 998d4083f7c7505238383465c42015a75743a9c6 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Wed, 1 Nov 2023 07:44:20 -0400 Subject: nabupc: Add nabu floppy disk formats (#11688) --- scripts/src/formats.lua | 11 ++ src/devices/bus/nabupc/fdc.cpp | 52 +++++++++- src/devices/bus/nabupc/fdc.h | 37 +------ src/lib/formats/all.cpp | 9 ++ src/lib/formats/nabupc_dsk.cpp | 229 +++++++++++++++++++++++++++++++++++++++++ src/lib/formats/nabupc_dsk.h | 53 ++++++++++ 6 files changed, 350 insertions(+), 41 deletions(-) create mode 100644 src/lib/formats/nabupc_dsk.cpp create mode 100644 src/lib/formats/nabupc_dsk.h diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua index 3ebfd3f8952..1ae8f710479 100644 --- a/scripts/src/formats.lua +++ b/scripts/src/formats.lua @@ -2318,4 +2318,15 @@ if opt_tool(FORMATS, "FS_HP98X5") then } end +-------------------------------------------------- +-- +--@src/lib/formats/nabupc_dsk.h,FORMATS["NABUPC_DSK"] = true +-------------------------------------------------- + +if opt_tool(FORMATS, "NABUPC_DSK") then + files { + MAME_DIR.. "src/lib/formats/nabupc_dsk.cpp", + MAME_DIR.. "src/lib/formats/nabupc_dsk.h", + } +end end diff --git a/src/devices/bus/nabupc/fdc.cpp b/src/devices/bus/nabupc/fdc.cpp index 3f6d3fc8fad..65afae9d2cd 100644 --- a/src/devices/bus/nabupc/fdc.cpp +++ b/src/devices/bus/nabupc/fdc.cpp @@ -9,18 +9,50 @@ #include "emu.h" #include "fdc.h" +#include "formats/nabupc_dsk.h" +#include "imagedev/floppy.h" +#include "machine/wd_fdc.h" //************************************************************************** // NABU PC FDC DEVICE //************************************************************************** +namespace { -DEFINE_DEVICE_TYPE(NABUPC_OPTION_FDC, bus::nabupc::fdc_device, "nabupc_option_fdc", "NABU PC Floppy Controller") +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +/* NABU PC FDC Device */ + +class fdc_device : public device_t, public bus::nabupc::device_option_expansion_interface +{ +public: + // construction/destruction + fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual uint8_t read(offs_t offset) override; + virtual void write(offs_t offset, uint8_t data) override; +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; +private: + void ds_w(uint8_t data); + + static void floppy_formats(format_registration &fr); + + required_device m_wd2797; + required_device_array m_floppies; +}; -namespace bus::nabupc { static void nabu_fdc_drives(device_slot_interface &device) { device.option_add("525dd", FLOPPY_525_DD); + device.option_add("35dd", FLOPPY_35_DD); } //------------------------------------------------- @@ -40,8 +72,8 @@ fdc_device::fdc_device(const machine_config &mconfig, const char *tag, device_t void fdc_device::device_add_mconfig(machine_config &config) { WD2797(config, m_wd2797, 4_MHz_XTAL / 4).set_force_ready(true); - FLOPPY_CONNECTOR(config, m_floppies[0], nabu_fdc_drives, "525dd", floppy_image_device::default_mfm_floppy_formats); - FLOPPY_CONNECTOR(config, m_floppies[1], nabu_fdc_drives, "525dd", floppy_image_device::default_mfm_floppy_formats); + FLOPPY_CONNECTOR(config, m_floppies[0], nabu_fdc_drives, "525dd", fdc_device::floppy_formats); + FLOPPY_CONNECTOR(config, m_floppies[1], nabu_fdc_drives, "525dd", fdc_device::floppy_formats); } //------------------------------------------------- @@ -60,6 +92,14 @@ void fdc_device::device_reset() m_wd2797->dden_w(0); } +//------------------------------------------------- +// supported floppy formats +//------------------------------------------------- +void fdc_device::floppy_formats(format_registration &fr) +{ + fr.add(FLOPPY_NABUPC_FORMAT); +} + //------------------------------------------------- // ds_w - write to drive select/density register //------------------------------------------------- @@ -119,4 +159,6 @@ void fdc_device::write(offs_t offset, uint8_t data) } } -} // namespace bus::nabupc +} // anonymous namespace + +DEFINE_DEVICE_TYPE_PRIVATE(NABUPC_OPTION_FDC, bus::nabupc::device_option_expansion_interface, fdc_device, "nabupc_option_fdc", "NABU PC Floppy Controller") diff --git a/src/devices/bus/nabupc/fdc.h b/src/devices/bus/nabupc/fdc.h index 49169746c79..864b5cc0353 100644 --- a/src/devices/bus/nabupc/fdc.h +++ b/src/devices/bus/nabupc/fdc.h @@ -13,42 +13,7 @@ #include "option.h" -#include "imagedev/floppy.h" -#include "machine/wd_fdc.h" - -namespace bus::nabupc { - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -/* NABU PC FDC Device */ - -class fdc_device : public device_t, public bus::nabupc::device_option_expansion_interface -{ -public: - // construction/destruction - fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t read(offs_t offset) override; - virtual void write(offs_t offset, uint8_t data) override; -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - // optional information overrides - virtual void device_add_mconfig(machine_config &config) override; -private: - void ds_w(uint8_t data); - - required_device m_wd2797; - required_device_array m_floppies; -}; - -} // namespace bus::nabupc - // device type definition -DECLARE_DEVICE_TYPE_NS(NABUPC_OPTION_FDC, bus::nabupc, fdc_device) +DECLARE_DEVICE_TYPE_NS(NABUPC_OPTION_FDC, bus::nabupc, device_option_expansion_interface) #endif // MAME_BUS_NABUPC_FDC_H diff --git a/src/lib/formats/all.cpp b/src/lib/formats/all.cpp index efc78e53911..02f5b636cf5 100644 --- a/src/lib/formats/all.cpp +++ b/src/lib/formats/all.cpp @@ -452,6 +452,10 @@ #include "mz_cas.h" #endif +#ifdef HAS_FORMATS_NABUPC_DSK +#include "nabupc_dsk.h" +#endif + #ifdef HAS_FORMATS_NANOS_DSK #include "nanos_dsk.h" #endif @@ -1225,6 +1229,11 @@ void mame_formats_full_list(mame_formats_enumerator &en) en.add(FLOPPY_MTX_FORMAT); // mtx_dsk.h #endif + en.category("NABU PC"); +#ifdef HAS_FORMATS_NABUPC_DSK + en.add(FLOPPY_NABUPC_FORMAT); // nabupc_dsk.h +#endif + en.category("Nanos"); #ifdef HAS_FORMATS_NANOS_DSK en.add(FLOPPY_NANOS_FORMAT); // nanos_dsk.h diff --git a/src/lib/formats/nabupc_dsk.cpp b/src/lib/formats/nabupc_dsk.cpp new file mode 100644 index 00000000000..c28d9f1ad3b --- /dev/null +++ b/src/lib/formats/nabupc_dsk.cpp @@ -0,0 +1,229 @@ +// license:BSD-3-Clause +// copyright-holders:Brian Johnson +/********************************************************************* + + formats/nabupc_dsk.cpp + + NABU PC floppy-disk images + + Disk Layouts: + 200k - 1 head , 40 tracks, 5 1024 byte sectors per track + 400k - 2 heads, 40 tracks, 5 1024 byte sectors per track + 800k - 2 heads, 80 tracks, 5 1024 byte sectors per track +*********************************************************************/ + +#include "nabupc_dsk.h" + +#include "imageutl.h" +#include "ioprocs.h" +#include "strformat.h" + +const nabupc_format::format nabupc_format::formats[] = +{ + { // 200k 40 track single sided double density (nabu) + floppy_image::FF_525, floppy_image::SSDD, + 40, 1, 32, 22, 80, + {0x00, 0x28, 0x00, 0x03, 0x07, 0x00, 0xC2, 0x00, 0x5F, 0x00, 0xE0, 0x00, 0x00, 0x18, 0x01, 0x00, 0x03, 0x07} + }, + { // 400k 40 track double sided double density (nabu) + floppy_image::FF_525, floppy_image::DSDD, + 40, 2, 32, 22, 80, + {0x01, 0x28, 0x00, 0x04, 0x0F, 0x01, 0xC4, 0x00, 0xBF, 0x00, 0xE0, 0x00, 0x00, 0x30, 0x01, 0x00, 0x03, 0x07} + }, + { // 800k 80 track double sided double density (nabu) + floppy_image::FF_35, floppy_image::DSDD, + 80, 2, 32, 22, 80, + {0x02, 0x28, 0x00, 0x04, 0x0F, 0x00, 0x8C, 0x01, 0x7F, 0x01, 0xFC, 0x00, 0x00, 0x61, 0x01, 0x00, 0x03, 0x07} + }, + {} +}; + +nabupc_format::nabupc_format() +{ +} + +int nabupc_format::find_format(util::random_read &io, uint32_t form_factor, const std::vector &variants) const +{ + uint64_t size; + if (io.length(size)) { + return -1; + } + + for (int i = 0; formats[i].form_factor; i++) { + const format &f = formats[i]; + + if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) { + continue; + } + if (!variants.empty() && !has_variant(variants, f.variant)) { + continue; + } + if (size == (uint64_t)sector_size * sector_count * f.track_count * f.head_count) { + LOG_FORMATS("nabupc: Found nabupc disk: %d\n", i); + return i; + } + LOG_FORMATS("nabupc: no match\n"); + } + return -1; +} + +int nabupc_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) const +{ + + int const format = find_format(io, form_factor, variants); + + if (format == -1) { + return 0; + } + + return FIFID_SIZE; +} + +void nabupc_format::build_nabu_track_mfm(int track, int head, floppy_image &image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_1, int gap_2, const uint8_t *dpb) +{ + std::vector track_data; + + if (dpb[1] != 0 && track == 0 && head == 0) { + for (int i = 0; i < 2; i++) raw_w(track_data, 16, 0x4489); + raw_w(track_data, 16, 0x1054); // 4e + for (int i = 0; i < 11; i++) mfm_w(track_data, 8, 0x4e); + mfm_w(track_data, 8, 0x19); + mfm_w(track_data, 8, 0x0F); + mfm_w(track_data, 8, 0x2D); + mfm_w(track_data, 8, 0x1A); + for (int i = 0; i < 18; i++) mfm_w(track_data, 8, dpb[i]); + } + + for (int i = 0; i < gap_1; i++) mfm_w(track_data, 8, 0x4e); + + int total_size = 0; + for (int i = 0; i < sector_count; i++) total_size += sects[i].actual_size; + + int etpos = int(track_data.size()) + (sector_count * (12 + 3 + 5 + 2 + gap_2 + 12 + 3 + 1+ 2) + total_size) * 16; + + if (etpos > cell_count) { + throw std::invalid_argument(util::string_format("Incorrect layout on track %d head %d, expected_size=%d, current_size=%d", track, head, cell_count, etpos)); + } + + if (etpos + gap_3 * 16 * (sector_count - 1) > cell_count) { + gap_3 = (cell_count - etpos) / 16 / (sector_count - 1); + } + + // Build the track + for (int i = 0; i < sector_count; i++) { + uint16_t crc; + // sync and IDAM and gap 2 + for (int j = 0; j < 12; j++) mfm_w(track_data, 8, 0x00); + unsigned int cpos = track_data.size(); + for (int j = 0; j < 3; j++) raw_w(track_data, 16, 0x4489); + mfm_w(track_data, 8, 0xfe); + mfm_w(track_data, 8, sects[i].track); + mfm_w(track_data, 8, sects[i].head); + mfm_w(track_data, 8, sects[i].sector); + mfm_w(track_data, 8, sects[i].size); + crc = calc_crc_ccitt(track_data, cpos, track_data.size()); + mfm_w(track_data, 16, crc); + for (int j = 0; j < gap_2; j++) mfm_w(track_data, 8, 0x4e); + + if (!sects[i].data) { + for (int j = 0; j < 12 + 4 + sects[i].actual_size + 2 + (i != sector_count - 1 ? gap_3 : 0); j++) mfm_w(track_data, 8, 0x4e); + } else { + // sync, DAM, data and gap 3 + for (int j = 0; j < 12; j++) mfm_w(track_data, 8, 0x00); + cpos = track_data.size(); + for (int j = 0; j < 3; j++) raw_w(track_data, 16, 0x4489); + mfm_w(track_data, 8, sects[i].deleted ? 0xf8 : 0xfb); + for (int j = 0; j < sects[i].actual_size; j++) mfm_w(track_data, 8, sects[i].data[j]); + crc = calc_crc_ccitt(track_data, cpos, track_data.size()); + if (sects[i].bad_crc) { + crc = 0xffff^crc; + } + mfm_w(track_data, 16, crc); + if (i != sector_count - 1) { + for (int j = 0; j < gap_3; j++) mfm_w(track_data, 8, 0x4e); + } + } + } + + // Gap 4b + + while (int(track_data.size()) < cell_count - 15) mfm_w(track_data, 8, 0x4e); + raw_w(track_data, cell_count - int(track_data.size()), 0x9254 >> (16 + int(track_data.size()) - cell_count)); + + generate_track_from_levels(track, head, track_data, 0, image); +} + +bool nabupc_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image &image) const +{ + int const type = find_format(io, form_factor, variants); + + if (type == -1) { + return false; + } + + const format &f = formats[type]; + + for (int track = 0; track < f.track_count; track++) { + for (int head = 0; head < f.head_count; head++) { + desc_pc_sector sects[sector_count]; + uint8_t sectdata[sector_count * sector_size]; + size_t actual; + io.read_at((track * f.head_count + head) * sector_count * sector_size, sectdata, sector_count * sector_size, actual); + for (int i = 0; i < sector_count; i++) { + sects[i].track = track; + sects[i].head = head; + sects[i].sector = i + 1; + sects[i].size = 3; + sects[i].actual_size = sector_size; + sects[i].data = sectdata + sector_size * i; + sects[i].deleted = false; + sects[i].bad_crc = false; + } + build_nabu_track_mfm(track, head, image, 100000, sector_count, sects, f.gap_3, f.gap_1, f.gap_2, f.dpb); + } + } + return true; +} + +bool nabupc_format::save(util::random_read_write &io, const std::vector &variants, const floppy_image &image) const +{ + + int heads, tracks; + image.get_actual_geometry(tracks, heads); + for (int track = 0; track < tracks; track++) { + for (int head = 0; head < heads; head++) { + uint64_t file_offset = (track * heads + head) * sector_count * sector_size; + auto bitstream = generate_bitstream_from_track(track, head, 2000, image); + auto sectors = extract_sectors_from_bitstream_mfm_pc(bitstream); + for (int i = 0; i < sector_count; i++) { + size_t actual; + io.write_at(file_offset, sectors[i + 1].data(), sector_size, actual); + file_offset += sector_size; + } + } + } + + return true; +} + +const char *nabupc_format::name() const noexcept +{ + return "nabupc"; +} + +const char *nabupc_format::description() const noexcept +{ + return "NABU PC CPM Disk Image"; +} + +const char *nabupc_format::extensions() const noexcept +{ + return "img,dsk"; +} + +bool nabupc_format::supports_save() const noexcept +{ + return true; +} + +const nabupc_format FLOPPY_NABUPC_FORMAT; diff --git a/src/lib/formats/nabupc_dsk.h b/src/lib/formats/nabupc_dsk.h new file mode 100644 index 00000000000..bedfe2a2e7b --- /dev/null +++ b/src/lib/formats/nabupc_dsk.h @@ -0,0 +1,53 @@ +// license:BSD-3-Clause +// copyright-holders:Brian Johnson +/********************************************************************* + + formats/nabupc_dsk.cpp + + NABU PC floppy-disk images + +*********************************************************************/ +#ifndef MAME_FORMATS_NABUPC_DSK_H +#define MAME_FORMATS_NABUPC_DSK_H + +#pragma once + +#include "flopimg.h" + +class nabupc_format : public floppy_image_format_t { +public: + struct format { + uint32_t form_factor; // See floppy_image for possible values + uint32_t variant; // See floppy_image for possible values + int track_count; + int head_count; + int gap_1; + int gap_2; + int gap_3; + uint8_t dpb[18]; + }; + + nabupc_format(); + + virtual const char *name() const noexcept override; + virtual const char *description() const noexcept override; + virtual const char *extensions() const noexcept override; + + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) const override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image &image) const override; + virtual bool save(util::random_read_write &io, const std::vector &variants, const floppy_image &image) const override; + + virtual bool supports_save() const noexcept override; + +protected: + static void build_nabu_track_mfm(int track, int head, floppy_image &image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_1, int gap_2, const uint8_t *dpb); + int find_format(util::random_read &io, uint32_t form_factor, const std::vector &variants) const; +private: + static constexpr int sector_count = 5; + static constexpr int sector_size = 1024; + static const format formats[]; +}; + +extern const nabupc_format FLOPPY_NABUPC_FORMAT; + +#endif // MAME_FORMATS_NABUPC_DSK_H -- cgit v1.2.3