86f_dsk: add read 86f image support

This commit is contained in:
cracyc 2024-10-15 20:15:25 -05:00
parent 53be466233
commit add6b45152
4 changed files with 307 additions and 0 deletions

View file

@ -75,6 +75,8 @@ project "formats"
MAME_DIR .. "src/lib/formats/fdi_dsk.cpp",
MAME_DIR .. "src/lib/formats/rpk.cpp",
MAME_DIR .. "src/lib/formats/rpk.h",
MAME_DIR .. "src/lib/formats/86f_dsk.cpp",
MAME_DIR .. "src/lib/formats/86f_dsk.h",
MAME_DIR .. "src/lib/formats/fsmgr.h",
MAME_DIR .. "src/lib/formats/fsmgr.cpp",

View file

@ -20,6 +20,7 @@
#include "formats/dsk_dsk.h"
#include "formats/pc_dsk.h"
#include "formats/ipf_dsk.h"
#include "formats/86f_dsk.h"
#include "formats/fs_unformatted.h"
#include "formats/fsblk_vec.h"
@ -164,6 +165,7 @@ void format_registration::add_fm_containers()
add(FLOPPY_MFM_FORMAT);
add(FLOPPY_TD0_FORMAT);
add(FLOPPY_IMD_FORMAT);
add(FLOPPY_86F_FORMAT);
}
void format_registration::add_mfm_containers()

241
src/lib/formats/86f_dsk.cpp Normal file
View file

@ -0,0 +1,241 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert, Carl
#include "86f_dsk.h"
#include "ioprocs.h"
#include <cstring>
#include <tuple>
#define _86F_FORMAT_HEADER "86BF"
#pragma pack(1)
struct _86FIMG
{
uint8_t headername[4];
uint8_t minor_version;
uint8_t major_version;
uint16_t flags;
uint32_t firsttrackoffs;
};
#pragma pack()
_86f_format::_86f_format() : floppy_image_format_t()
{
}
const char *_86f_format::name() const noexcept
{
return "86f";
}
const char *_86f_format::description() const noexcept
{
return "86f floppy image";
}
const char *_86f_format::extensions() const noexcept
{
return "86f";
}
bool _86f_format::supports_save() const noexcept
{
return false;
}
int _86f_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t header[4];
auto const [err, actual] = read_at(io, 0, &header, sizeof(header));
if (err) {
return 0;
}
if (!memcmp(header, _86F_FORMAT_HEADER, 4)) {
return FIFID_SIGN;
}
return 0;
}
void _86f_format::generate_track_from_bitstream_with_weak(int track, int head, const uint8_t *trackbuf, const uint8_t *weak, int index_cell, int track_size, floppy_image &image) const
{
int j = 0;
std::vector<uint32_t> &dest = image.get_buffer(track, head);
dest.clear();
for(int i=index_cell; i != track_size; i++, j++) {
int databit = trackbuf[i >> 3] & (0x80 >> (i & 7));
int weakbit = weak ? weak[i >> 3] & (0x80 >> (i & 7)) : 0;
if(weakbit && databit)
dest.push_back(floppy_image::MG_D | (j*2+1));
else if(weakbit && !databit)
dest.push_back(floppy_image::MG_N | (j*2+1));
else if(databit)
dest.push_back(floppy_image::MG_F | (j*2+1));
}
for(int i=0; i != index_cell; i++, j++) {
int databit = trackbuf[i >> 3] & (0x80 >> (i & 7));
int weakbit = weak ? weak[i >> 3] & (0x80 >> (i & 7)) : 0;
if(weakbit && databit)
dest.push_back(floppy_image::MG_D | (j*2+1));
else if(weakbit && !databit)
dest.push_back(floppy_image::MG_N | (j*2+1));
else if(databit)
dest.push_back(floppy_image::MG_F | (j*2+1));
}
normalize_times(dest, track_size*2);
image.set_write_splice_position(track, head, 0, 0);
}
bool _86f_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
std::error_condition err;
size_t actual;
_86FIMG header;
// read header
std::tie(err, actual) = read_at(io, 0, &header, sizeof(header));
if(err || (actual != sizeof(header)))
return false;
int drivecyl, driveheads;
image.get_maximal_geometry(drivecyl, driveheads);
bool skip_odd = drivecyl < 50;
int imagesides = header.flags & TWO_SIDES ? 2 : 1;
int sides = (imagesides == 2) && (driveheads == 2) ? 2 : 1;
std::vector<uint32_t> tracklist;
int tracklistsize = header.firsttrackoffs - 8;
tracklist.resize(tracklistsize / 4);
std::tie(err, actual) = read_at(io, 8, &tracklist[0], tracklistsize);
if(err || (actual != tracklistsize))
return false;
uint32_t tracklen = 0;
if((header.flags & (TOTAL_BC | EXTRA_BC | RPM_MASK)) != (TOTAL_BC | EXTRA_BC)) {
switch(header.flags & (RPM_MASK | RPM_FAST | TYPE_MASK)) {
case TYPE_DD | RPM_2:
case TYPE_HD | RPM_2:
tracklen = 12750;
break;
case TYPE_DD | RPM_15:
case TYPE_HD | RPM_15:
tracklen = 12687;
break;
case TYPE_DD | RPM_1:
case TYPE_HD | RPM_1:
tracklen = 12625;
break;
case TYPE_DD | RPM_0:
case TYPE_HD | RPM_0:
tracklen = 12500;
break;
case TYPE_DD | RPM_1 | RPM_FAST:
case TYPE_HD | RPM_1 | RPM_FAST:
tracklen = 12376;
break;
case TYPE_DD | RPM_15 | RPM_FAST:
case TYPE_HD | RPM_15 | RPM_FAST:
tracklen = 12315;
break;
case TYPE_DD | RPM_2 | RPM_FAST:
case TYPE_HD | RPM_2 | RPM_FAST:
tracklen = 12254;
break;
case TYPE_ED | RPM_2:
tracklen = 25500;
break;
case TYPE_ED | RPM_15:
tracklen = 25375;
break;
case TYPE_ED | RPM_1:
tracklen = 25250;
break;
case TYPE_ED | RPM_0:
tracklen = 25000;
break;
case TYPE_ED | RPM_1 | RPM_FAST:
tracklen = 25752;
break;
case TYPE_ED | RPM_15 | RPM_FAST:
tracklen = 24630;
break;
case TYPE_ED | RPM_2 | RPM_FAST:
tracklen = 24509;
break;
}
}
uint32_t trackoff;
int trackinfolen = header.flags & EXTRA_BC ? 10 : 6;
if(skip_odd)
drivecyl *= 2;
std::vector<uint8_t> trackbuf;
std::vector<uint8_t> weakbuf;
int track;
for(track=0; (track < (tracklistsize / 4)) && (track < drivecyl); track++) {
for(int side=0; side < sides; side++) {
trackoff = tracklist[(track * imagesides) + side];
if(!trackoff) break;
if(!skip_odd || track%2 == 0) {
char trackinfo[10];
std::tie(err, actual) = read_at(io, trackoff, &trackinfo, trackinfolen); // FIXME: check for errors and premature EOF
if(err || (actual != trackinfolen))
return false;
uint32_t bitcells = tracklen << 4;
uint32_t index_cell;
if(header.flags & EXTRA_BC)
{
uint32_t extra = *(uint32_t *)(trackinfo + 2);
index_cell = *(uint32_t *)(trackinfo + 6);
if((header.flags & TOTAL_BC) && !tracklen)
bitcells = extra;
else
bitcells += (int32_t)extra;
}
else
index_cell = *(uint32_t *)(trackinfo + 2);
uint32_t fulltracklen = (bitcells >> 3) + (bitcells & 7 ? 1 : 0);
uint8_t *weak = nullptr;
trackbuf.resize(fulltracklen);
std::tie(err, actual) = read_at(io, trackoff + trackinfolen, &trackbuf[0], fulltracklen);
if(err || (actual != fulltracklen))
return false;
if(header.flags & SURFACE_DESC)
{
weakbuf.resize(fulltracklen);
std::tie(err, actual) = read_at(io, trackoff + trackinfolen + fulltracklen, &weakbuf[0], fulltracklen);
if(err || (actual != fulltracklen))
return false;
weak = &weakbuf[0];
}
if(skip_odd) {
generate_track_from_bitstream_with_weak(track/2, side, &trackbuf[0], weak, index_cell, bitcells, image);
}
else {
generate_track_from_bitstream_with_weak(track, side, &trackbuf[0], weak, index_cell, bitcells, image);
}
}
}
if(!trackoff) break;
}
if(imagesides == 2)
image.set_variant(track > 50 ? floppy_image::DSHD : floppy_image::DSDD);
else
image.set_variant(floppy_image::SSDD);
return true;
}
/*
bool _86f_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const
{
return true;
}
*/
const _86f_format FLOPPY_86F_FORMAT;

62
src/lib/formats/86f_dsk.h Normal file
View file

@ -0,0 +1,62 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert, Carl
/*********************************************************************
formats/86f_dsk.h
86f disk images
*********************************************************************/
#ifndef MAME_FORMATS_86F_DSK_H
#define MAME_FORMATS_86F_DSK_H
#pragma once
#include "flopimg.h"
class _86f_format : public floppy_image_format_t
{
public:
_86f_format();
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;
//virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const override;
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;
private:
void generate_track_from_bitstream_with_weak(int track, int head, const uint8_t *trackbuf, const uint8_t *weak, int index_cell, int track_size, floppy_image &image) const;
enum
{
SURFACE_DESC = 1,
TYPE_MASK = 6,
TYPE_DD = 0,
TYPE_HD = 2,
TYPE_ED = 4,
TYPE_ED2000 = 6,
TWO_SIDES = 8,
WRITE_PROTECT = 0x10,
RPM_MASK = 0x60,
RPM_0 = 0,
RPM_1 = 0x20,
RPM_15 = 0x40,
RPM_2 = 0x60,
EXTRA_BC = 0x80,
ZONED_RPM = 0x100,
ZONE_PREA2_1 = 0,
ZONE_PREA2_2 = 0x200,
ZONE_A2 = 0x400,
ZONE_C64 = 0x600,
BIG_ENDIAN = 0x800,
RPM_FAST = 0x1000,
TOTAL_BC = 0x1000
};
};
extern const _86f_format FLOPPY_86F_FORMAT;
#endif // MAME_FORMATS_86F_DSK_H