diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua index 5ae22a556c8..6bb724e3e40 100644 --- a/scripts/src/formats.lua +++ b/scripts/src/formats.lua @@ -833,6 +833,18 @@ if (FORMATS["FLEX_DSK"]~=null or _OPTIONS["with-tools"]) then } end +-------------------------------------------------- +-- +--@src/lib/formats/uniflex_dsk.h,FORMATS["UNIFLEX_DSK"] = true +-------------------------------------------------- + +if (FORMATS["UNIFLEX_DSK"]~=null or _OPTIONS["with-tools"]) then + files { + MAME_DIR.. "src/lib/formats/uniflex_dsk.cpp", + MAME_DIR.. "src/lib/formats/uniflex_dsk.h", + } +end + -------------------------------------------------- -- --@src/lib/formats/fm7_cas.h,FORMATS["FM7_CAS"] = true diff --git a/src/lib/formats/uniflex_dsk.cpp b/src/lib/formats/uniflex_dsk.cpp new file mode 100644 index 00000000000..646fdcc68b1 --- /dev/null +++ b/src/lib/formats/uniflex_dsk.cpp @@ -0,0 +1,150 @@ +// license:BSD-3-Clause +// copyright-holders:68bit +/* + * uniflex_dsk.c - UniFLEX compatible disk images + * + * The UniFLEX floppy disk format is distinctily different to the FLEX format, + * the sector size is 512 byte sectors versus 256 byte sectors and the format + * of the disk information is different, and the file system format is + * different. + */ + +#include "uniflex_dsk.h" +#include "formats/imageutl.h" + +uniflex_format::uniflex_format() : wd177x_format(formats) +{ +} + +const char *uniflex_format::name() const +{ + return "uniflex"; +} + +const char *uniflex_format::description() const +{ + return "UniFLEX compatible disk image"; +} + +const char *uniflex_format::extensions() const +{ + return "dsk"; +} + +int uniflex_format::identify(io_generic *io, uint32_t form_factor) +{ + int type = find_size(io, form_factor); + + if (type != -1) + return 75; + return 0; +} + +int uniflex_format::find_size(io_generic *io, uint32_t form_factor) +{ + uint64_t size = io_generic_size(io); + uint8_t sir[192]; + + // Look at the SIR sector, the second sector. + io_generic_read(io, sir, 1 * 512, sizeof(sir)); + + uint16_t fdn_block_count = pick_integer_be(sir, 0x10, 2); + uint32_t last_block_number = pick_integer_be(sir, 0x12, 3); + uint32_t free_block_count = pick_integer_be(sir, 0x15, 3); + uint16_t fdn_free_count = pick_integer_be(sir, 0x15, 2); + + uint16_t volume_number = pick_integer_be(sir, 0x36, 2); + uint8_t disk_density = sir[0x3a]; + uint8_t disk_side_info = sir[0x3b]; + + uint32_t volbc_start_addr = pick_integer_be(sir, 0x3c, 3); + uint16_t swap_size = pick_integer_be(sir, 0x3f, 2); + + LOG_FORMATS("UniFLEX floppy dsk size %d\n", (uint32_t)size); + LOG_FORMATS(" time = %lu %lu\n", pick_integer_be(sir, 0x08, 4), pick_integer_be(sir, 0x0c, 4)); + LOG_FORMATS(" fdn_block_count: %d\n", fdn_block_count); + + LOG_FORMATS(" file system name: "); + for (int i = 0; i < 14; i++) + LOG_FORMATS(" %02x", sir[0x1a + i]); + LOG_FORMATS("\n"); + + LOG_FORMATS(" volume name: "); + for (int i = 0; i < 14; i++) + LOG_FORMATS(" %02x", sir[0x28 + i]); + LOG_FORMATS("\n"); + + LOG_FORMATS(" last_block_number: %d\n", last_block_number); + LOG_FORMATS(" free_block_count: %d\n", free_block_count); + LOG_FORMATS(" fdn_free_count: %d\n", fdn_free_count); + LOG_FORMATS(" volume_number: %d\n", volume_number); + LOG_FORMATS(" disk density: %02x, side info %02x\n", disk_density, disk_side_info); + LOG_FORMATS(" volbc_start_addr: %d\n", volbc_start_addr); + LOG_FORMATS(" swap_size: %d\n", swap_size); + + // The first eight bytes appear to be zeros. + if (pick_integer_be(sir, 0x00, 8) != 0) + 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(size != (uint64_t)compute_track_size(f) * f.track_count * f.head_count) + continue; + + // Check consistency with the SIR sector. + if(last_block_number + 1 + swap_size != f.sector_count * f.track_count * f.head_count) + continue; + if(f.head_count == 2 && disk_side_info == 0) + continue; + if(f.encoding == floppy_image::MFM && disk_density == 0) + continue; + if(f.encoding == floppy_image::FM && disk_density != 0) + continue; + + return i; + } + return -1; +} + +// UniFLEX numbers sectors on the second side of a track continuing from the +// first side which is a variation not handled by the generic code. +void uniflex_format::build_sector_description(const format &f, uint8_t *sectdata, desc_s *sectors, int track, int head) const +{ + if(f.sector_base_id == -1) { + for(int i=0; i; diff --git a/src/lib/formats/uniflex_dsk.h b/src/lib/formats/uniflex_dsk.h new file mode 100644 index 00000000000..cd3a3c515ab --- /dev/null +++ b/src/lib/formats/uniflex_dsk.h @@ -0,0 +1,32 @@ +// license:BSD-3-Clause +// copyright-holders:68bit +/* + * uniflex_dsk.h + */ +#ifndef MAME_FORMATS_UNIFLEX_DSK_H +#define MAME_FORMATS_UNIFLEX_DSK_H + +#pragma once + +#include "flopimg.h" +#include "wd177x_dsk.h" + +class uniflex_format : public wd177x_format +{ +public: + uniflex_format(); + + virtual const char *name() const override; + virtual const char *description() const override; + virtual const char *extensions() const override; + virtual int identify(io_generic *io, uint32_t form_factor) override; + virtual int find_size(io_generic *io, uint32_t form_factor) override; + void build_sector_description(const format &f, uint8_t *sectdata, desc_s *sectors, int track, int head) const override; + +private: + static const format formats[]; +}; + +extern const floppy_format_type FLOPPY_UNIFLEX_FORMAT; + +#endif // MAME_FORMATS_UNIFLEX_DSK_H diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp index f07e6ec9ad2..1953e7b0538 100644 --- a/src/tools/floptool.cpp +++ b/src/tools/floptool.cpp @@ -55,6 +55,9 @@ #include "formats/aim_dsk.h" #include "formats/m20_dsk.h" +#include "formats/flex_dsk.h" +#include "formats/uniflex_dsk.h" + static floppy_format_type floppy_formats[] = { FLOPPY_MFI_FORMAT, @@ -98,7 +101,10 @@ static floppy_format_type floppy_formats[] = { FLOPPY_DVK_MX_FORMAT, FLOPPY_AIM_FORMAT, - FLOPPY_M20_FORMAT + FLOPPY_M20_FORMAT, + + FLOPPY_FLEX_FORMAT, + FLOPPY_UNIFLEX_FORMAT }; void CLIB_DECL ATTR_PRINTF(1,2) logerror(const char *format, ...)