From d93d41a780e6bfea499136f866058c11f2c25945 Mon Sep 17 00:00:00 2001 From: "Michael R. Furman" Date: Thu, 25 Aug 2022 12:03:15 -0700 Subject: [PATCH 1/2] Add FDOS disk format for the SWTPC 6800 The FDOS Operating System was released by SWTPC in 1977 along with the MF-68 Mini Disk System and was superceeded by FLEX a few months later. This change adds support to boot FDOS on the SWTPC 6800 machine in MAME using a specific disk image (FDOSMPS.DSK) from deramp.com (Mike Douglas) and can also read/write the other available disk images. --- scripts/src/formats.lua | 12 +++ src/devices/bus/ss50/dc5.cpp | 2 + src/lib/formats/all.cpp | 4 + src/lib/formats/fdos_dsk.cpp | 185 +++++++++++++++++++++++++++++++++++ src/lib/formats/fdos_dsk.h | 30 ++++++ 5 files changed, 233 insertions(+) create mode 100644 src/lib/formats/fdos_dsk.cpp create mode 100644 src/lib/formats/fdos_dsk.h diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua index 064d70ab99211..e293b6502c75e 100644 --- a/scripts/src/formats.lua +++ b/scripts/src/formats.lua @@ -911,6 +911,18 @@ if opt_tool(FORMATS, "CP68_DSK") then } end +-------------------------------------------------- +-- +--@src/lib/formats/fdos_dsk.h,FORMATS["FDOS_DSK"] = true +-------------------------------------------------- + +if opt_tool(FORMATS, "FDOS_DSK") then + files { + MAME_DIR.. "src/lib/formats/fdos_dsk.cpp", + MAME_DIR.. "src/lib/formats/fdos_dsk.h", + } +end + -------------------------------------------------- -- --@src/lib/formats/uniflex_dsk.h,FORMATS["UNIFLEX_DSK"] = true diff --git a/src/devices/bus/ss50/dc5.cpp b/src/devices/bus/ss50/dc5.cpp index 90b7f40d4d157..d3c105bc2a858 100644 --- a/src/devices/bus/ss50/dc5.cpp +++ b/src/devices/bus/ss50/dc5.cpp @@ -32,6 +32,7 @@ #include "machine/wd_fdc.h" #include "imagedev/floppy.h" #include "formats/cp68_dsk.h" +#include "formats/fdos_dsk.h" #include "formats/flex_dsk.h" #include "formats/os9_dsk.h" #include "formats/uniflex_dsk.h" @@ -242,6 +243,7 @@ void ss50_dc5_device::floppy_formats(format_registration &fr) fr.add_mfm_containers(); fr.add(FLOPPY_FLEX_FORMAT); fr.add(FLOPPY_CP68_FORMAT); + fr.add(FLOPPY_FDOS_FORMAT); fr.add(FLOPPY_OS9_FORMAT); fr.add(FLOPPY_UNIFLEX_FORMAT); } diff --git a/src/lib/formats/all.cpp b/src/lib/formats/all.cpp index 14f605cf92fb2..9a7b53b730937 100644 --- a/src/lib/formats/all.cpp +++ b/src/lib/formats/all.cpp @@ -272,6 +272,10 @@ #include "cp68_dsk.h" #endif +#ifdef HAS_FORMATS_FDOS_DSK +#include "fdos_dsk.h" +#endif + #ifdef HAS_FORMATS_FLEX_DSK #include "flex_dsk.h" #endif diff --git a/src/lib/formats/fdos_dsk.cpp b/src/lib/formats/fdos_dsk.cpp new file mode 100644 index 0000000000000..da4e7ace10fc0 --- /dev/null +++ b/src/lib/formats/fdos_dsk.cpp @@ -0,0 +1,185 @@ +// license:BSD-3-Clause copyright-holders:Michael R. Furman +/* + * fdos_dsk.cpp - FDOS compatible disk images + * + * Created on: 24/08/2022 + * + * This FDOS floppy disk image support leverages the wd177x_format support with + * verification of the disk formatting and the the ability to support format + * variations. + * + * The FDOS Disk format is as follows: + * + * Geometry:: 10 Sectors * 35 Tracks * 256 Bytes * 1 Side + * Sectors Numbered from 0-9 + * Gap Bytes: Verified from FDOS source code + * + * Disk Format:: + * + * Operating System:: Tracks 0-1 + * Directory:: Track 2 + * Data:: Tracks 3-34 + * + * + * Note: Due to hardware differences between the original DC-1 (WD1771) + * controller for which FDOS was designed and DC-4 (WD1797) or DC-5 (WD2797) + * Controllers (DC-5 is Emulated in MAME), the machine can only be booted with + * a specific disk image from deramp.com (Mike Douglas) at the following + * location. The other disks available in the same directory can then be read + * once FDOS is loaded. This disk image also works on real hardware with a DC-4 + * or PT FD-2A controllers. + * + * https://deramp.com/downloads/swtpc/software/FDOS/Disk%20Images/FDOSMPS.DSK + * + * This disk contains the all of these required patches: + * + * https://deramp.com/downloads/swtpc/software/FDOS/Disk%20Images/Patches/ + */ + +#include "fdos_dsk.h" + +#include "imageutl.h" + +#include "ioprocs.h" + +namespace +{ + class fdos_formats : public wd177x_format + { + public: + struct dirent_entry_fdos + { + char filename[8]{}; + char password[8]{}; + uint8_t start_track = 0; + uint8_t start_sector = 0; + uint8_t num_sectors[2] = {}; + uint8_t file_type = 0; + uint8_t start_addr[2] = {}; + uint8_t end_addr[2] = {}; + uint8_t exec_addr[2] = {}; + uint8_t basic_high_line[2] = {}; + uint8_t spares[3] = {}; + }; + + static const format formats[]; + }; +} + +fdos_format::fdos_format() : wd177x_format(fdos_formats::formats) +{ +} + +const char *fdos_format::name() const +{ + return "fdos"; +} + +const char *fdos_format::description() const +{ + return "FDOS compatible disk image"; +} + +const char *fdos_format::extensions() const +{ + return "dsk"; +} + +int fdos_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) const +{ + int type = find_size(io, form_factor, variants); + + if (type != -1) + return FIFID_SIZE; + return 0; +} + + +int fdos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) const +{ + uint64_t size; + if (io.length(size)) + return -1; + + uint8_t boot0[256]; + fdos_formats::dirent_entry_fdos info; + size_t actual; + std::error_condition ec; + + for (int i=0; fdos_formats::formats[i].form_factor; i++) { + const format &f = fdos_formats::formats[i]; + + // Format Check + // Check byte 0 and byte 3 of Track 0 Sector 0 + // 00320 2400 BD 240C START JSR BOOT + // 00330 2403 DE OB RESTRT LDX PROGX + // Should be $BD and $DE respectively + // There could be additional variations + ec = io.read_at(0, &boot0, f.sector_base_size, actual); + if (ec || actual != f.sector_base_size) + return -1; + if (boot0[0] != 0xbd && boot0[3] != 0xde) + continue; + + LOG_FORMATS("FDOS floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", + (uint32_t)size, + (uint32_t)size / f.sector_base_size, + (uint32_t)size % f.sector_base_size, + form_factor); + + // Directory entries start at Track 2 Sector 0 + ec = io.read_at(2 * f.sector_count * f.sector_base_size, &info, sizeof(struct fdos_formats::dirent_entry_fdos), actual); + if (ec || actual != sizeof(struct fdos_formats::dirent_entry_fdos)) + continue; + + // First directory entry should be "$DOS" + if (memcmp(info.filename, "$DOS ", 8) != 0) + continue; + if (memcmp(info.password, " ", 8) != 0) + continue; + if (info.start_track != 0) + continue; + if (info.start_sector != 0) + continue; + if ((info.num_sectors[0]<<8 | info.num_sectors[1]) != 0x0014) + continue; + // $DOS File type is supposed to be $11 but some disks (FDOSMPS) have $00 + if (info.file_type != 0 && info.file_type != 0x11) + continue; + if ((info.start_addr[0]<<8 | info.start_addr[1]) != 0x2400) + continue; + if ((info.end_addr[0]<<8 | info.end_addr[1]) != 0x2fff) + continue; + // FDOS entry is supposed to be $2600 but some disks have $2400 + uint16_t exec = info.exec_addr[0]<<8 | info.exec_addr[1]; + if (exec != 0x2600 && exec != 0x2400) + continue; + + + unsigned int format_size = 0; + for (int track=0; track < f.track_count; track++) { + for (int head=0; head < f.head_count; head++) { + const format &tf = get_track_format(f, head, track); + format_size += compute_track_size(tf); + } + } + + if (format_size != size) + continue; + + + LOG_FORMATS("FDOS matching format index %d\n", i); + return i; + } + return -1; +} + +const fdos_formats::format fdos_formats::formats[] = { + { // 0 89.6K 5 1/4 inch single density fdos format + floppy_image::FF_525, floppy_image::SSSD, floppy_image::FM, + 4000, 10, 35, 1, 256, {}, 0, {}, 11, 11, 11 + }, + {} +}; + +const fdos_format FLOPPY_FDOS_FORMAT; diff --git a/src/lib/formats/fdos_dsk.h b/src/lib/formats/fdos_dsk.h new file mode 100644 index 0000000000000..62687b43d7b65 --- /dev/null +++ b/src/lib/formats/fdos_dsk.h @@ -0,0 +1,30 @@ +// license:BSD-3-Clause +// copyright-holders:Michael R. Furman +/* + * fdos_dsk.h + * + * Created on: 24/08/2022 + */ +#ifndef MAME_FORMATS_FDOS_DSK_H +#define MAME_FORMATS_FDOS_DSK_H + +#pragma once + +#include "flopimg.h" +#include "wd177x_dsk.h" + +class fdos_format : public wd177x_format +{ +public: + fdos_format(); + + virtual const char *name() const override; + virtual const char *description() const override; + virtual const char *extensions() const override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) const override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) const override; +}; + +extern const fdos_format FLOPPY_FDOS_FORMAT; + +#endif // MAME_FORMATS_FDOS_DSK_H From 2dcb3bde6d0e4e8e9a0fde9f3353a0fc005d9a11 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sun, 28 Aug 2022 07:04:43 +1000 Subject: [PATCH 2/2] fdos_dsk.cpp: Consistency --- src/lib/formats/fdos_dsk.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/formats/fdos_dsk.cpp b/src/lib/formats/fdos_dsk.cpp index da4e7ace10fc0..8c505fe5258bb 100644 --- a/src/lib/formats/fdos_dsk.cpp +++ b/src/lib/formats/fdos_dsk.cpp @@ -49,8 +49,8 @@ namespace public: struct dirent_entry_fdos { - char filename[8]{}; - char password[8]{}; + char filename[8] = {}; + char password[8] = {}; uint8_t start_track = 0; uint8_t start_sector = 0; uint8_t num_sectors[2] = {}; @@ -121,10 +121,10 @@ int fdos_format::find_size(util::random_read &io, uint32_t form_factor, const st if (boot0[0] != 0xbd && boot0[3] != 0xde) continue; - LOG_FORMATS("FDOS floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", - (uint32_t)size, - (uint32_t)size / f.sector_base_size, - (uint32_t)size % f.sector_base_size, + LOG_FORMATS("FDOS floppy dsk: size %u bytes, %u total sectors, %u remaining bytes, expected form factor %x\n", + size, + size / f.sector_base_size, + size % f.sector_base_size, form_factor); // Directory entries start at Track 2 Sector 0