summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--hash/to_flop.xml5
-rw-r--r--scripts/src/formats.lua12
-rw-r--r--src/devices/bus/thomson/cd90_015.cpp2
-rw-r--r--src/devices/bus/thomson/cd90_351.cpp2
-rw-r--r--src/devices/bus/thomson/cd90_640.cpp2
-rw-r--r--src/lib/formats/all.cpp7
-rw-r--r--src/lib/formats/sap_dsk.cpp168
-rw-r--r--src/lib/formats/sap_dsk.h30
-rw-r--r--src/mame/thomson/thomson.cpp2
9 files changed, 227 insertions, 3 deletions
diff --git a/hash/to_flop.xml b/hash/to_flop.xml
index 924698a67ca..9bafb2fa81c 100644
--- a/hash/to_flop.xml
+++ b/hash/to_flop.xml
@@ -5,9 +5,8 @@ license:CC0-1.0
Thanks to DCMOTO (http://dcmoto.free.fr) for info!
-FIXME: Many of these images should be 5.25" rather than 3.5". (The old custom Thomson floppy emulation didn't care about form factor.)
-TODO: SAP format is not currently supported.
-TBD: Which images are compatible with which systems?
+FIXME: Some images should be 5.25" rather than 3.5", though TO8/TO9/TO9+ software can assumed to be the latter.
+ (The old custom Thomson floppy emulation didn't care about form factor, and many images are probably conversions.)
-->
<softwarelist name="to_flop" description="Thomson TO-series floppy disks">
diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua
index 320f2123674..fa0d3d5f8dc 100644
--- a/scripts/src/formats.lua
+++ b/scripts/src/formats.lua
@@ -1773,6 +1773,18 @@ end
--------------------------------------------------
--
+--@src/lib/formats/sap_dsk.h,FORMATS["SAP_DSK"] = true
+--------------------------------------------------
+
+if opt_tool(FORMATS, "SAP_DSK") then
+ files {
+ MAME_DIR.. "src/lib/formats/sap_dsk.cpp",
+ MAME_DIR.. "src/lib/formats/sap_dsk.h",
+ }
+end
+
+--------------------------------------------------
+--
--@src/lib/formats/sc3000_bit.h,FORMATS["SC3000_BIT"] = true
--------------------------------------------------
diff --git a/src/devices/bus/thomson/cd90_015.cpp b/src/devices/bus/thomson/cd90_015.cpp
index 86e132301d4..f51b47f4dd2 100644
--- a/src/devices/bus/thomson/cd90_015.cpp
+++ b/src/devices/bus/thomson/cd90_015.cpp
@@ -8,6 +8,7 @@
#include "emu.h"
#include "cd90_015.h"
+#include "formats/sap_dsk.h"
#include "formats/thom_dsk.h"
DEFINE_DEVICE_TYPE(CD90_015, cd90_015_device, "cd90_015", "Thomson CD 90-015 floppy drive controller")
@@ -78,6 +79,7 @@ void cd90_015_device::floppy_drives(device_slot_interface &device)
void cd90_015_device::floppy_formats(format_registration &fr)
{
fr.add(FLOPPY_THOMSON_525_FORMAT);
+ fr.add(FLOPPY_SAP_FORMAT);
}
void cd90_015_device::device_add_mconfig(machine_config &config)
diff --git a/src/devices/bus/thomson/cd90_351.cpp b/src/devices/bus/thomson/cd90_351.cpp
index 870c0843733..1247a2c3185 100644
--- a/src/devices/bus/thomson/cd90_351.cpp
+++ b/src/devices/bus/thomson/cd90_351.cpp
@@ -10,6 +10,7 @@
#include "emu.h"
#include "cd90_351.h"
+#include "formats/sap_dsk.h"
#include "formats/thom_dsk.h"
#include "machine/thmfc1.h"
@@ -60,6 +61,7 @@ void cd90_351_device::floppy_formats(format_registration &fr)
{
fr.add_pc_formats();
fr.add(FLOPPY_THOMSON_35_FORMAT);
+ fr.add(FLOPPY_SAP_FORMAT);
}
void cd90_351_device::device_add_mconfig(machine_config &config)
diff --git a/src/devices/bus/thomson/cd90_640.cpp b/src/devices/bus/thomson/cd90_640.cpp
index a49d579704e..ba8a9a95969 100644
--- a/src/devices/bus/thomson/cd90_640.cpp
+++ b/src/devices/bus/thomson/cd90_640.cpp
@@ -7,6 +7,7 @@
#include "emu.h"
#include "cd90_640.h"
+#include "formats/sap_dsk.h"
#include "formats/thom_dsk.h"
DEFINE_DEVICE_TYPE(CD90_640, cd90_640_device, "cd90_640", "Thomson CD 90-640 floppy drive controller")
@@ -49,6 +50,7 @@ void cd90_640_device::floppy_drives(device_slot_interface &device)
void cd90_640_device::floppy_formats(format_registration &fr)
{
fr.add(FLOPPY_THOMSON_525_FORMAT);
+ fr.add(FLOPPY_SAP_FORMAT);
}
void cd90_640_device::device_add_mconfig(machine_config &config)
diff --git a/src/lib/formats/all.cpp b/src/lib/formats/all.cpp
index 02f5b636cf5..c068969db2e 100644
--- a/src/lib/formats/all.cpp
+++ b/src/lib/formats/all.cpp
@@ -576,6 +576,10 @@
#include "rx50_dsk.h"
#endif
+#ifdef HAS_FORMATS_SAP_DSK
+#include "sap_dsk.h"
+#endif
+
#ifdef HAS_FORMATS_SC3000_BIT
#include "sc3000_bit.h"
#endif
@@ -1339,6 +1343,9 @@ void mame_formats_full_list(mame_formats_enumerator &en)
en.add(FLOPPY_THOMSON_525_FORMAT); // thom_dsk.h
en.add(FLOPPY_THOMSON_35_FORMAT); // thom_dsk.h
#endif
+#ifdef HAS_FORMATS_SAP_DSK
+ en.add(FLOPPY_SAP_FORMAT);
+#endif
en.category("Texas Instruments");
#ifdef HAS_FORMATS_TI99_DSK
diff --git a/src/lib/formats/sap_dsk.cpp b/src/lib/formats/sap_dsk.cpp
new file mode 100644
index 00000000000..6809b8bab29
--- /dev/null
+++ b/src/lib/formats/sap_dsk.cpp
@@ -0,0 +1,168 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#include "sap_dsk.h"
+
+#include "ioprocs.h"
+#include "multibyte.h"
+
+static constexpr unsigned HEADER_LENGTH = 66;
+static constexpr uint8_t MAGIC_XOR = 0xb3;
+
+const sap_dsk_format FLOPPY_SAP_FORMAT;
+
+inline uint16_t sap_dsk_format::accumulate_crc(uint16_t crc, uint8_t data) noexcept
+{
+ // Almost CRC16-CCITT, but not quite...
+ for (int shift : {0, 4})
+ crc = ((crc >> 4) & 0xfff) ^ 0x1081 * ((crc ^ (data >> shift)) & 0xf);
+ return crc;
+}
+
+const char *sap_dsk_format::name() const noexcept
+{
+ return "sap_dsk";
+}
+
+const char *sap_dsk_format::description() const noexcept
+{
+ return "Thomson SAP disk image (Systeme d'Archivage Pukall)";
+}
+
+const char *sap_dsk_format::extensions() const noexcept
+{
+ return "sap";
+}
+
+bool sap_dsk_format::supports_save() const noexcept
+{
+ return false;
+}
+
+int sap_dsk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
+{
+ uint8_t buffer[HEADER_LENGTH];
+ auto [err, actual] = read_at(io, 0, buffer, HEADER_LENGTH);
+ if (err || actual != HEADER_LENGTH)
+ return 0;
+
+ // Check ID string
+ if (memcmp(&buffer[1], "SYSTEME D'ARCHIVAGE PUKALL S.A.P. (c) Alexandre PUKALL Avril 1998", HEADER_LENGTH - 1) != 0)
+ return 0;
+
+ // Check disk format
+ if (form_factor == floppy_image::FF_35)
+ {
+ // 3.5" disks must have 80 double-density tracks
+ if ((buffer[0] & 0x7f) != 0x01)
+ return 0;
+ }
+ else if (form_factor == floppy_image::FF_525)
+ {
+ // 5.25" disks must have 40 tracks
+ if ((buffer[0] & 0x7e) != 0x02)
+ return 0;
+ }
+ else if (form_factor != floppy_image::FF_UNKNOWN)
+ return 0;
+
+ uint32_t expected_size = HEADER_LENGTH + uint32_t((buffer[0] & 0x01) ? 256 + 6 : 128 + 6) * ((buffer[0] & 0x02) ? 40 : 80) * 16 * ((buffer[0] & 0x80) ? 2 : 1);
+ uint64_t actual_size;
+ if (!io.length(actual_size) && expected_size == actual_size)
+ return FIFID_SIGN | FIFID_SIZE;
+ else
+ return FIFID_SIGN;
+}
+
+bool sap_dsk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
+{
+ uint8_t disk_type;
+ if (auto [err, actual] = read_at(io, 0, &disk_type, 1); err || actual != 1)
+ return false;
+
+ int track_count = (disk_type & 0x02) ? 40 : 80;
+ int head_count = (disk_type & 0x80) ? 2 : 1;
+ int max_tracks, max_heads;
+ image.get_maximal_geometry(max_tracks, max_heads);
+ if (max_heads < head_count || max_tracks < track_count)
+ return false;
+
+ switch (disk_type & 0x03)
+ {
+ case 0x01:
+ image.set_form_variant(floppy_image::FF_35, (disk_type & 0x80) ? floppy_image::DSDD : floppy_image::SSDD);
+ break;
+
+ case 0x02:
+ image.set_form_variant(floppy_image::FF_525, (disk_type & 0x80) ? floppy_image::DSSD : floppy_image::SSSD);
+ break;
+
+ case 0x03:
+ image.set_form_variant(floppy_image::FF_525, (disk_type & 0x80) ? floppy_image::DSDD : floppy_image::SSDD);
+ break;
+
+ default:
+ return false;
+ }
+
+ uint8_t sector_buf[16 * 1024];
+ uint8_t sector_header[4];
+ uint8_t sector_crc[2];
+ desc_pc_sector sectors[16];
+
+ size_t read_offset = HEADER_LENGTH;
+ for (int head = 0; head < head_count; head++)
+ {
+ for (int track = 0; track < track_count; track++)
+ {
+ uint8_t *bufptr = &sector_buf[0];
+ uint8_t track_size = 16;
+ int sector_count = 0;
+ bool is_mfm = disk_type & 0x01;
+ while (track_size != 0)
+ {
+ if (auto [err, actual] = read_at(io, read_offset, &sector_header[0], 4); err || actual != 4)
+ return false;
+ if (sector_count == 0 && sector_header[0] == 1)
+ is_mfm = false;
+ uint8_t sector_size = (sector_header[0] & 2) ? 4 >> (sector_header[0] & 1) : 1;
+ if (track_size < sector_size)
+ return false;
+ uint16_t sector_octets = sector_size * (is_mfm ? 256 : 128);
+ if (auto [err, actual] = read_at(io, read_offset + 4, bufptr, sector_octets); err || actual != sector_octets)
+ return false;
+ if (auto [err, actual] = read_at(io, read_offset + 4 + sector_octets, &sector_crc[0], 2); err || actual != 2)
+ return false;
+
+ uint16_t crc = 0xffff;
+ for (uint8_t data : sector_header)
+ crc = accumulate_crc(crc, data);
+ for (uint16_t i = 0; i < sector_octets; i++)
+ {
+ bufptr[i] ^= MAGIC_XOR;
+ crc = accumulate_crc(crc, bufptr[i]);
+ }
+
+ sectors[sector_count].track = sector_header[2];
+ sectors[sector_count].head = head;
+ sectors[sector_count].sector = sector_header[3];
+ sectors[sector_count].size = sector_size;
+ sectors[sector_count].actual_size = sector_octets;
+ sectors[sector_count].data = bufptr;
+ sectors[sector_count].deleted = false;
+ sectors[sector_count].bad_crc = crc != get_u16be(sector_crc);
+
+ read_offset += sector_octets + 6;
+ bufptr += sector_octets;
+ track_size -= sector_size;
+ sector_count++;
+ }
+ if (is_mfm)
+ build_pc_track_mfm(track, head, image, 100000, sector_count, sectors, calc_default_pc_gap3_size(form_factor, sectors[0].actual_size));
+ else
+ build_pc_track_fm(track, head, image, 100000 / 2, sector_count, sectors, calc_default_pc_gap3_size(form_factor, sectors[0].actual_size));
+ }
+ }
+
+ return true;
+}
diff --git a/src/lib/formats/sap_dsk.h b/src/lib/formats/sap_dsk.h
new file mode 100644
index 00000000000..5bc86a2d6ef
--- /dev/null
+++ b/src/lib/formats/sap_dsk.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_FORMATS_SAP_DSK_H
+#define MAME_FORMATS_SAP_DSK_H
+
+#pragma once
+
+#include "flopimg.h"
+
+class sap_dsk_format : public floppy_image_format_t
+{
+public:
+ sap_dsk_format() = default;
+
+ virtual const char *name() const noexcept override;
+ virtual const char *description() const noexcept override;
+ virtual const char *extensions() const noexcept override;
+ virtual bool supports_save() 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;
+
+private:
+ static inline uint16_t accumulate_crc(uint16_t crc, uint8_t data) noexcept;
+};
+
+extern const sap_dsk_format FLOPPY_SAP_FORMAT;
+
+#endif // MAME_FORMATS_SAP_DSK_H
diff --git a/src/mame/thomson/thomson.cpp b/src/mame/thomson/thomson.cpp
index 856987ef807..8c1ae828082 100644
--- a/src/mame/thomson/thomson.cpp
+++ b/src/mame/thomson/thomson.cpp
@@ -97,6 +97,7 @@
#include "softlist_dev.h"
#include "speaker.h"
+#include "formats/sap_dsk.h"
#include "formats/thom_cas.h"
#include "formats/thom_dsk.h"
@@ -494,6 +495,7 @@ static void to35_floppy_formats(format_registration &fr)
{
fr.add_pc_formats();
fr.add(FLOPPY_THOMSON_35_FORMAT);
+ fr.add(FLOPPY_SAP_FORMAT);
}
/* ------------ driver ------------ */