nabupc: Add nabu floppy disk formats (#11688)

This commit is contained in:
Brian Johnson 2023-11-01 07:44:20 -04:00 committed by GitHub
parent 99db2cfc76
commit 998d4083f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 350 additions and 41 deletions

View File

@ -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

View File

@ -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<wd2797_device> m_wd2797;
required_device_array<floppy_connector, 2> 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")

View File

@ -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<wd2797_device> m_wd2797;
required_device_array<floppy_connector, 2> 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

View File

@ -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

View File

@ -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<uint32_t> &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<uint32_t> &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<uint32_t> 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<uint32_t> &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<uint32_t> &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;

View File

@ -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<uint32_t> &variants) const override;
virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const override;
virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &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<uint32_t> &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