Add support for reading SAP (Systeme d'Archivage Pukall) disk images to Thomson systems

This commit is contained in:
AJR 2024-11-03 17:43:13 -05:00
parent bccdfc9e04
commit eb2a834625
9 changed files with 227 additions and 3 deletions

View File

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

View File

@ -1771,6 +1771,18 @@ if opt_tool(FORMATS, "RX50_DSK") then
}
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

View File

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

View File

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

View File

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

View File

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

168
src/lib/formats/sap_dsk.cpp Normal file
View File

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

30
src/lib/formats/sap_dsk.h Normal file
View File

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

View File

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