summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats')
-rw-r--r--src/lib/formats/apridisk.h2
-rw-r--r--src/lib/formats/dsk_dsk.cpp6
-rw-r--r--src/lib/formats/hpi_dsk.cpp96
-rw-r--r--src/lib/formats/hpi_dsk.h3
-rw-r--r--src/lib/formats/mtx_dsk.cpp53
-rw-r--r--src/lib/formats/mtx_dsk.h33
-rw-r--r--src/lib/formats/opd_dsk.cpp61
-rw-r--r--src/lib/formats/opd_dsk.h38
8 files changed, 272 insertions, 20 deletions
diff --git a/src/lib/formats/apridisk.h b/src/lib/formats/apridisk.h
index 81db4b41105..1155a0b4a9a 100644
--- a/src/lib/formats/apridisk.h
+++ b/src/lib/formats/apridisk.h
@@ -33,7 +33,7 @@ private:
static const int APR_HEADER_SIZE = 128;
// sector types
- enum
+ enum : uint32_t
{
APR_DELETED = 0xe31d0000,
APR_SECTOR = 0xe31d0001,
diff --git a/src/lib/formats/dsk_dsk.cpp b/src/lib/formats/dsk_dsk.cpp
index 5b019fb53d1..c90579b68d0 100644
--- a/src/lib/formats/dsk_dsk.cpp
+++ b/src/lib/formats/dsk_dsk.cpp
@@ -362,6 +362,12 @@ bool dsk_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
skip = 2;
}
int tracks = header[0x30];
+
+ int img_tracks, img_heads;
+ image->get_maximal_geometry(img_tracks, img_heads);
+ if (tracks > img_tracks || heads > img_heads)
+ return false;
+
uint64_t track_offsets[84*2];
int cnt =0;
if (!extendformat) {
diff --git a/src/lib/formats/hpi_dsk.cpp b/src/lib/formats/hpi_dsk.cpp
index 8d23f151862..50d2653280d 100644
--- a/src/lib/formats/hpi_dsk.cpp
+++ b/src/lib/formats/hpi_dsk.cpp
@@ -4,9 +4,10 @@
hpi_dsk.cpp
- HP9895A "HPI" disk images
+ HP9885/HP9895A "HPI" disk images
- CHS = 77/2/30
+ CHS = 67/1/30 (SSDD)
+ CHS = 77/2/30 (DSDD)
Sector size 256 bytes
Cell size 2 µs
Gap1 = 16 x 0x00
@@ -40,7 +41,7 @@
256 bytes per sector). There's also a "reduced" version holding
just 75 cylinders.
When loading, the disk image is translated to MMFM encoding so
- that it can be loaded into HP9895 emulator.
+ that it can be loaded into HP9885/HP9895 emulator.
*********************************************************************/
@@ -65,11 +66,14 @@ constexpr int ID_DATA_OFFSET = 30 * 16; // Nominal distance (in cells) between I
// Size of image file (holding 77 cylinders)
constexpr unsigned HPI_IMAGE_SIZE = HPI_TRACKS * HPI_HEADS * HPI_SECTORS * HPI_SECTOR_SIZE;
constexpr unsigned HPI_RED_TRACKS = 75; // Reduced number of tracks
+constexpr unsigned HPI_9885_TRACKS = 67; // Tracks visible to HP9885 drives
// Size of reduced image file (holding 75 cylinders)
constexpr unsigned HPI_RED_IMAGE_SIZE = HPI_RED_TRACKS * HPI_HEADS * HPI_SECTORS * HPI_SECTOR_SIZE;
hpi_format::hpi_format()
{
+ (void)HPI_IMAGE_SIZE;
+ (void)HPI_RED_IMAGE_SIZE;
}
int hpi_format::identify(io_generic *io, uint32_t form_factor)
@@ -79,27 +83,79 @@ int hpi_format::identify(io_generic *io, uint32_t form_factor)
// we try to stay back and give only 50 points, since another image
// format may also have images of the same size (there is no header and no
// magic number for HPI format...
+ unsigned dummy_heads;
+ unsigned dummy_tracks;
if (((form_factor == floppy_image::FF_8) || (form_factor == floppy_image::FF_UNKNOWN)) &&
- ((size == HPI_RED_IMAGE_SIZE) || (size == HPI_IMAGE_SIZE))) {
+ geometry_from_size(size , dummy_heads , dummy_tracks)) {
return 50;
} else {
return 0;
}
}
+bool hpi_format::geometry_from_size(uint64_t image_size , unsigned& heads , unsigned& tracks)
+{
+ if ((image_size % HPI_SECTOR_SIZE) != 0) {
+ // Not a whole number of sectors
+ return false;
+ }
+ unsigned sectors = unsigned(image_size / HPI_SECTOR_SIZE);
+ if ((sectors % HPI_SECTORS) != 0) {
+ // Not a whole number of tracks
+ return false;
+ }
+ unsigned tot_tracks = sectors / HPI_SECTORS;
+ // Possible combinations
+ //
+ // | Tot tracks | Heads | Tracks | Format |
+ // |------------+-------+--------+--------|
+ // | 67 | 1 | 67 | SSDD |
+ // | 77 | 1 | 77 | SSDD |
+ // | 150 | 2 | 75 | DSDD |
+ // | 154 | 2 | 77 | DSDD |
+ //
+ switch (tot_tracks) {
+ case HPI_9885_TRACKS:
+ heads = 1;
+ tracks = HPI_9885_TRACKS;
+ return true;
+
+ case HPI_TRACKS:
+ heads = 1;
+ tracks = HPI_TRACKS;
+ return true;
+
+ case HPI_RED_TRACKS * 2:
+ heads = 2;
+ tracks = HPI_RED_TRACKS;
+ return true;
+
+ case HPI_TRACKS * 2:
+ heads = 2;
+ tracks = HPI_TRACKS;
+ return true;
+
+ default:
+ return false;
+ }
+}
+
bool hpi_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
{
- image->set_variant(floppy_image::DSDD); // We actually need to derive the variant from the image size depending on the form factor
+ unsigned heads;
+ unsigned cylinders;
uint64_t size = io_generic_size(io);
- unsigned cylinders;
- if (size == HPI_RED_IMAGE_SIZE) {
- cylinders = HPI_RED_TRACKS;
- } else if (size == HPI_IMAGE_SIZE) {
- cylinders = HPI_TRACKS;
- } else {
+ if (!geometry_from_size(size, heads, cylinders)) {
+ return false;
+ }
+ int max_tracks;
+ int max_heads;
+ image->get_maximal_geometry(max_tracks , max_heads);
+ if (cylinders > max_tracks || heads > max_heads) {
return false;
}
+ image->set_variant(heads == 2 ? floppy_image::DSDD : floppy_image::SSDD);
// Suck in the whole image
std::vector<uint8_t> image_data(size);
@@ -118,11 +174,11 @@ bool hpi_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
unsigned list_offset = 0;
for (unsigned cyl = 0; cyl < cylinders; cyl++) {
- for (unsigned head = 0; head < HPI_HEADS; head++) {
+ for (unsigned head = 0; head < heads; head++) {
std::vector<uint32_t> track_data;
for (unsigned sector = 0; sector < HPI_SECTORS; sector++) {
unsigned real_sector = sector_list[ (sector + list_offset) % HPI_SECTORS ];
- unsigned offset_in_image = chs_to_lba(cyl, head, real_sector) * HPI_SECTOR_SIZE;
+ unsigned offset_in_image = chs_to_lba(cyl, head, real_sector, heads) * HPI_SECTOR_SIZE;
write_sector(track_data , cyl , real_sector + (head << 7) , &image_data[ offset_in_image ]);
}
fill_with_gap3(track_data);
@@ -135,8 +191,12 @@ bool hpi_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
bool hpi_format::save(io_generic *io, floppy_image *image)
{
- for (unsigned cyl = 0; cyl < HPI_TRACKS; cyl++) {
- for (unsigned head = 0; head < HPI_HEADS; head++) {
+ int tracks;
+ int heads;
+ image->get_actual_geometry(tracks, heads);
+
+ for (int cyl = 0; cyl < tracks; cyl++) {
+ for (int head = 0; head < heads; head++) {
uint8_t bitstream[ 21000 ];
int bitstream_size;
generate_bitstream_from_track(cyl , head , CELL_SIZE , bitstream , bitstream_size , image , 0);
@@ -145,7 +205,7 @@ bool hpi_format::save(io_generic *io, floppy_image *image)
uint8_t sector_data[ HPI_SECTOR_SIZE ];
while (get_next_sector(bitstream , bitstream_size , pos , track_no , head_no , sector_no , sector_data)) {
if (track_no == cyl && head_no == head && sector_no < HPI_SECTORS) {
- unsigned offset_in_image = chs_to_lba(cyl, head, sector_no) * HPI_SECTOR_SIZE;
+ unsigned offset_in_image = chs_to_lba(cyl, head, sector_no, heads) * HPI_SECTOR_SIZE;
io_generic_write(io, sector_data, offset_in_image, HPI_SECTOR_SIZE);
}
}
@@ -300,9 +360,9 @@ void hpi_format::fill_with_gap3(std::vector<uint32_t> &buffer)
}
}
-unsigned hpi_format::chs_to_lba(unsigned cylinder , unsigned head , unsigned sector)
+unsigned hpi_format::chs_to_lba(unsigned cylinder , unsigned head , unsigned sector , unsigned heads)
{
- return sector + (head + cylinder * HPI_HEADS) * HPI_SECTORS;
+ return sector + (head + cylinder * heads) * HPI_SECTORS;
}
std::vector<uint8_t> hpi_format::get_next_id_n_block(const uint8_t *bitstream , int bitstream_size , int& pos , int& start_pos)
diff --git a/src/lib/formats/hpi_dsk.h b/src/lib/formats/hpi_dsk.h
index 8457db1ea24..287f37fd302 100644
--- a/src/lib/formats/hpi_dsk.h
+++ b/src/lib/formats/hpi_dsk.h
@@ -36,6 +36,7 @@ public:
private:
typedef std::array<uint8_t , HPI_SECTORS> sector_list_t;
+ static bool geometry_from_size(uint64_t image_size , unsigned& heads , unsigned& tracks);
static void interleaved_sectors(unsigned il_factor , sector_list_t& sector_list);
void write_mmfm_bit(std::vector<uint32_t> &buffer , bool data_bit , bool clock_bit);
void write_mmfm_byte(std::vector<uint32_t> &buffer , uint8_t data , uint8_t clock = 0);
@@ -43,7 +44,7 @@ private:
void write_crc(std::vector<uint32_t> &buffer , uint16_t crc);
void write_sector(std::vector<uint32_t> &buffer , uint8_t track_no , uint8_t sect_head_no , const uint8_t *sect_data);
void fill_with_gap3(std::vector<uint32_t> &buffer);
- static unsigned chs_to_lba(unsigned cylinder , unsigned head , unsigned sector);
+ static unsigned chs_to_lba(unsigned cylinder , unsigned head , unsigned sector , unsigned heads);
std::vector<uint8_t> get_next_id_n_block(const uint8_t *bitstream , int bitstream_size , int& pos , int& start_pos);
bool get_next_sector(const uint8_t *bitstream , int bitstream_size , int& pos , unsigned& track , unsigned& head , unsigned& sector , uint8_t *sector_data);
diff --git a/src/lib/formats/mtx_dsk.cpp b/src/lib/formats/mtx_dsk.cpp
new file mode 100644
index 00000000000..95420f40aab
--- /dev/null
+++ b/src/lib/formats/mtx_dsk.cpp
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Memotech MTX
+
+ Disk image format
+
+***************************************************************************/
+
+#include "mtx_dsk.h"
+
+mtx_format::mtx_format() : wd177x_format(formats)
+{
+}
+
+const char *mtx_format::name() const
+{
+ return "mtx";
+}
+
+const char *mtx_format::description() const
+{
+ return "Memotech MTX disk image";
+}
+
+const char *mtx_format::extensions() const
+{
+ return "mfloppy";
+}
+
+const mtx_format::format mtx_format::formats[] =
+{
+ { // 320k 5 1/4 inch double density single sided (Type 03)
+ floppy_image::FF_525, floppy_image::DSDD, floppy_image::MFM,
+ 2000, 16, 40, 2, 256, {}, 1, {}, 32, 22, 54
+ },
+ { // 640k 5 1/4 inch double density double sided (Type 07)
+ floppy_image::FF_525, floppy_image::DSQD, floppy_image::MFM,
+ 2000, 16, 80, 2, 256, {}, 1, {}, 32, 22, 54
+ },
+ { // 320k 3 1/2 inch double density single sided (Type 03)
+ floppy_image::FF_35, floppy_image::DSDD, floppy_image::MFM,
+ 2000, 16, 40, 2, 256, {}, 1, {}, 32, 22, 54
+ },
+ { // 640k 3 1/2 inch double density double sided (Type 07)
+ floppy_image::FF_35, floppy_image::DSQD, floppy_image::MFM,
+ 2000, 16, 80, 2, 256, {}, 1, {}, 32, 22, 54
+ },
+ {}
+};
+
+const floppy_format_type FLOPPY_MTX_FORMAT = &floppy_image_format_creator<mtx_format>;
diff --git a/src/lib/formats/mtx_dsk.h b/src/lib/formats/mtx_dsk.h
new file mode 100644
index 00000000000..86f74bccfc5
--- /dev/null
+++ b/src/lib/formats/mtx_dsk.h
@@ -0,0 +1,33 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Memotech MTX
+
+ Disk image format
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __MTX_DSK_H__
+#define __MTX_DSK_H__
+
+#include "wd177x_dsk.h"
+
+class mtx_format : public wd177x_format
+{
+public:
+ mtx_format();
+
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+ virtual const char *extensions() const override;
+
+private:
+ static const format formats[];
+};
+
+extern const floppy_format_type FLOPPY_MTX_FORMAT;
+
+#endif // __MTX_DSK_H__
diff --git a/src/lib/formats/opd_dsk.cpp b/src/lib/formats/opd_dsk.cpp
new file mode 100644
index 00000000000..b45b58762ed
--- /dev/null
+++ b/src/lib/formats/opd_dsk.cpp
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Sinclair ZX Spectrum
+
+ Opus Discovery disk image formats
+
+***************************************************************************/
+
+#include "opd_dsk.h"
+
+
+opd_format::opd_format() : wd177x_format(formats)
+{
+}
+
+const char *opd_format::name() const
+{
+ return "opd";
+}
+
+const char *opd_format::description() const
+{
+ return "Opus Discovery disk image";
+}
+
+const char *opd_format::extensions() const
+{
+ return "opd,opu";
+}
+
+int opd_format::identify(io_generic *io, uint32_t form_factor)
+{
+ int type = find_size(io, form_factor);
+
+ if (type != -1)
+ return 90;
+ return 0;
+}
+
+int opd_format::get_image_offset(const format &f, int head, int track)
+{
+ return (f.track_count * head + track) * compute_track_size(f);
+}
+
+const opd_format::format opd_format::formats[] =
+{
+ { // 180k 40 track single sided double density - gaps unverified
+ floppy_image::FF_35, floppy_image::SSSD, floppy_image::MFM,
+ 2000, 18, 40, 1, 256, {}, 0, {}, 36, 22, 27
+ },
+ { // 360k 40 track double sided double density - gaps unverified
+ floppy_image::FF_35, floppy_image::DSSD, floppy_image::MFM,
+ 2000, 18, 40, 2, 256, {}, 0, {}, 36, 22, 27
+ },
+ {}
+};
+
+
+const floppy_format_type FLOPPY_OPD_FORMAT = &floppy_image_format_creator<opd_format>;
diff --git a/src/lib/formats/opd_dsk.h b/src/lib/formats/opd_dsk.h
new file mode 100644
index 00000000000..3eb018ca1dc
--- /dev/null
+++ b/src/lib/formats/opd_dsk.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Sinclair ZX Spectrum
+
+ Opus Discovery disk image formats
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef OPD_DSK_H
+#define OPD_DSK_H
+
+#include "flopimg.h"
+#include "wd177x_dsk.h"
+
+
+class opd_format : public wd177x_format
+{
+public:
+ opd_format();
+
+ virtual int identify(io_generic *io, uint32_t form_factor) override;
+ virtual int get_image_offset(const format &f, int head, int track) override;
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+ virtual const char *extensions() const override;
+
+private:
+ static const format formats[];
+};
+
+
+extern const floppy_format_type FLOPPY_OPD_FORMAT;
+
+#endif // OPD_DSK_H