summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/wd177x_dsk.cpp
diff options
context:
space:
mode:
author 68bit <info@68bit.org>2020-02-04 16:14:07 +1100
committer 68bit <info@68bit.org>2020-02-08 00:12:05 +1100
commita87c3b6f7a988271974d38d0fd445a85dde7c09b (patch)
tree98a5ac7cd3daa9bd9bfbef03b60f5ba0c07cce37 /src/lib/formats/wd177x_dsk.cpp
parent927906163401b32433f18d2d92c72f196bc1f7f8 (diff)
wd177x_dsk: generalize to allow custom track format variations
Add a get_track_format() method that can be overridden to supply format variations for any track and head. The code is generalised to account for such variations. The default method returns the passed format, so this change is neutral for existing formats. Simplify the FLEX DSK format code. There are now simply format variation descriptions for the second track that have the sector ID continuing in sequence from the first track, rather than specialized code. Extend the FLEX format to support variations in the sectors ID of the first two sectors. The FLEX 6800 boot sectors have IDs based at zero rather than one. Extend the FLEX format to support variations for which the first track, on both sides, is single density on an otherwise double density disk which was historically a common format. Extend the OS9 disk format to support variations for which the first track, on only the first side, is single density on an otherwise double density disk. OS9 for the SWTPC and Gimix typically used such formats. Extend the OS9 disk format to support variations with a base sector ID of zero in contrast to the existing COCO OS9 format which uses a based sector ID of one. The OS9 format identification code is extended to rely on the optional information stored in the OS9 LSN0 header to identify COCO format disks, and all COCO format disks appear to have this optional information in a regular enough format.
Diffstat (limited to 'src/lib/formats/wd177x_dsk.cpp')
-rw-r--r--src/lib/formats/wd177x_dsk.cpp213
1 files changed, 129 insertions, 84 deletions
diff --git a/src/lib/formats/wd177x_dsk.cpp b/src/lib/formats/wd177x_dsk.cpp
index 69915f0f396..f19e9d4cbb2 100644
--- a/src/lib/formats/wd177x_dsk.cpp
+++ b/src/lib/formats/wd177x_dsk.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert
+// copyright-holders:Olivier Galibert, 68bit
/*********************************************************************
formats/wd177x_dsk.h
@@ -16,6 +16,16 @@ wd177x_format::wd177x_format(const format *_formats)
formats = _formats;
}
+// Default implementation. May be overwritten by subclasses to handle tracks
+// that vary from the default, such as a FM encoded track on a largely MFM
+// encoded disk, or a track with an different sector IDs etc. Only the track
+// encoding is used from the returned format, the number of track_count is not
+// accessed.
+const wd177x_format::format &wd177x_format::get_track_format(const format &f, int head, int track)
+{
+ return f;
+}
+
/*
Default implementation for find_size. May be overwritten by subclasses.
*/
@@ -27,7 +37,15 @@ int wd177x_format::find_size(io_generic *io, uint32_t form_factor)
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)
+ uint64_t format_size = 0;
+ for(int track=0; track < f.track_count; track++) {
+ for(int head=0; head < f.head_count; head++) {
+ const format &tf = get_track_format(f, head, track);
+ format_size += compute_track_size(tf);
+ }
+ }
+
+ if(size == format_size)
return i;
}
return -1;
@@ -42,6 +60,7 @@ int wd177x_format::identify(io_generic *io, uint32_t form_factor)
return 0;
}
+// A track specific format is to be supplied.
int wd177x_format::compute_track_size(const format &f) const
{
int track_size;
@@ -55,6 +74,7 @@ int wd177x_format::compute_track_size(const format &f) const
return track_size;
}
+// A track specific format is to be supplied.
void wd177x_format::build_sector_description(const format &f, uint8_t *sectdata, desc_s *sectors, int track, int head) const
{
if(f.sector_base_id == -1) {
@@ -78,6 +98,7 @@ void wd177x_format::build_sector_description(const format &f, uint8_t *sectdata,
}
}
+// A track specific format is to be supplied.
floppy_image_format_t::desc_e* wd177x_format::get_desc_fm(const format &f, int &current_size, int &end_gap_index)
{
static floppy_image_format_t::desc_e desc[23] = {
@@ -125,6 +146,7 @@ floppy_image_format_t::desc_e* wd177x_format::get_desc_fm(const format &f, int &
return desc;
}
+// A track specific format is to be supplied.
floppy_image_format_t::desc_e* wd177x_format::get_desc_mfm(const format &f, int &current_size, int &end_gap_index)
{
static floppy_image_format_t::desc_e desc[25] = {
@@ -181,46 +203,46 @@ bool wd177x_format::load(io_generic *io, uint32_t form_factor, floppy_image *ima
return false;
const format &f = formats[type];
- floppy_image_format_t::desc_e *desc;
- int current_size;
- int end_gap_index;
-
- switch (f.encoding)
- {
- case floppy_image::FM:
- desc = get_desc_fm(f, current_size, end_gap_index);
- break;
- case floppy_image::MFM:
- default:
- desc = get_desc_mfm(f, current_size, end_gap_index);
- break;
- }
-
- int total_size = 200000000/f.cell_size;
- int remaining_size = total_size - current_size;
- if(remaining_size < 0)
- throw emu_fatalerror("wd177x_format: Incorrect track layout, max_size=%d, current_size=%d", total_size, current_size);
- // Fixup the end gap
- desc[end_gap_index].p2 = remaining_size / 16;
- desc[end_gap_index + 1].p2 = remaining_size & 15;
- desc[end_gap_index + 1].p1 >>= 16-(remaining_size & 15);
+ for(int track=0; track < f.track_count; track++)
+ for(int head=0; head < f.head_count; head++) {
+ uint8_t sectdata[40*512];
+ desc_s sectors[40];
+ floppy_image_format_t::desc_e *desc;
+ int current_size;
+ int end_gap_index;
+ const format &tf = get_track_format(f, head, track);
+
+ switch (tf.encoding)
+ {
+ case floppy_image::FM:
+ desc = get_desc_fm(tf, current_size, end_gap_index);
+ break;
+ case floppy_image::MFM:
+ default:
+ desc = get_desc_mfm(tf, current_size, end_gap_index);
+ break;
+ }
- int track_size = compute_track_size(f);
+ int total_size = 200000000/tf.cell_size;
+ int remaining_size = total_size - current_size;
+ if(remaining_size < 0)
+ throw emu_fatalerror("wd177x_format: Incorrect track layout, max_size=%d, current_size=%d", total_size, current_size);
- uint8_t sectdata[40*512];
- desc_s sectors[40];
+ // Fixup the end gap
+ desc[end_gap_index].p2 = remaining_size / 16;
+ desc[end_gap_index + 1].p2 = remaining_size & 15;
+ desc[end_gap_index + 1].p1 >>= 16-(remaining_size & 15);
- for(int track=0; track < f.track_count; track++)
- for(int head=0; head < f.head_count; head++) {
- if (f.encoding == floppy_image::FM)
- desc[14].p1 = get_track_dam_fm(f, head, track);
+ if (tf.encoding == floppy_image::FM)
+ desc[14].p1 = get_track_dam_fm(tf, head, track);
else
- desc[16].p1 = get_track_dam_mfm(f, head, track);
+ desc[16].p1 = get_track_dam_mfm(tf, head, track);
- build_sector_description(f, sectdata, sectors, track, head);
+ build_sector_description(tf, sectdata, sectors, track, head);
+ int track_size = compute_track_size(tf);
io_generic_read(io, sectdata, get_image_offset(f, head, track), track_size);
- generate_track(desc, track, head, sectors, f.sector_count, total_size, image);
+ generate_track(desc, track, head, sectors, tf.sector_count, total_size, image);
}
image->set_variant(f.variant);
@@ -252,7 +274,7 @@ bool wd177x_format::save(io_generic *io, floppy_image *image)
// Build the list of all formats for the immediately superior cell size
int cur_cell_size = 0;
candidates.clear();
- for(int i=0; i != formats_count; i++) {
+ for(int i=0; i < formats_count; i++) {
if(image->get_form_factor() == floppy_image::FF_UNKNOWN ||
image->get_form_factor() == formats[i].form_factor) {
if(formats[i].cell_size == cur_cell_size)
@@ -273,7 +295,7 @@ bool wd177x_format::save(io_generic *io, floppy_image *image)
if(candidates.empty())
break;
- // Filter with track 0 head 0
+ // Filter
check_compatibility(image, candidates);
// Nobody matches, try with the next cell size
@@ -293,7 +315,7 @@ bool wd177x_format::save(io_generic *io, floppy_image *image)
int tracks, heads;
image->get_actual_geometry(tracks, heads);
chosen_candidate = candidates[0];
- for(unsigned int i=1; i != candidates.size(); i++) {
+ for(unsigned int i=1; i < candidates.size(); i++) {
const format &cc = formats[chosen_candidate];
const format &cn = formats[candidates[i]];
@@ -334,19 +356,20 @@ bool wd177x_format::save(io_generic *io, floppy_image *image)
if(chosen_candidate == -1)
chosen_candidate = 0;
-
const format &f = formats[chosen_candidate];
- int track_size = compute_track_size(f);
uint8_t sectdata[40*512];
desc_s sectors[40];
- for(int track=0; track < f.track_count; track++)
+ for(int track=0; track < f.track_count; track++) {
for(int head=0; head < f.head_count; head++) {
- build_sector_description(f, sectdata, sectors, track, head);
- extract_sectors(image, f, sectors, track, head);
+ const format &tf = get_track_format(f, head, track);
+ build_sector_description(tf, sectdata, sectors, track, head);
+ extract_sectors(image, tf, sectors, track, head);
+ int track_size = compute_track_size(tf);
io_generic_write(io, sectdata, get_image_offset(f, head, track), track_size);
}
+ }
return true;
}
@@ -357,15 +380,32 @@ bool wd177x_format::save(io_generic *io, floppy_image *image)
*/
int wd177x_format::get_image_offset(const format &f, int head, int track)
{
- return (track * f.head_count + head) * compute_track_size(f);
+ int offset = 0;
+
+ for(int trk=0; trk < track; trk++) {
+ for(int hd=0; hd < f.head_count; hd++) {
+ const format &tf = get_track_format(f, hd, trk);
+ offset += compute_track_size(tf);
+ }
+ }
+
+ for(int hd=0; hd < head; hd++) {
+ const format &tf = get_track_format(f, hd, track);
+ offset += compute_track_size(tf);
+ }
+
+
+ return offset;
}
+// A track specific format is to be supplied.
int wd177x_format::get_track_dam_fm(const format &f, int head, int track)
{
// everything marked as data by default
return FM_DAM;
}
+// A track specific format is to be supplied.
int wd177x_format::get_track_dam_mfm(const format &f, int head, int track)
{
// everything marked as data by default
@@ -374,57 +414,62 @@ int wd177x_format::get_track_dam_mfm(const format &f, int head, int track)
void wd177x_format::check_compatibility(floppy_image *image, std::vector<int> &candidates)
{
- uint8_t bitstream[500000/8];
- uint8_t sectdata[50000];
- desc_xs sectors[256];
- int track_size;
-
- // Extract the sectors
- generate_bitstream_from_track(0, 0, formats[candidates[0]].cell_size, bitstream, track_size, image);
-
- switch (formats[candidates[0]].encoding)
- {
- case floppy_image::FM:
- extract_sectors_from_bitstream_fm_pc(bitstream, track_size, sectors, sectdata, sizeof(sectdata));
- break;
- case floppy_image::MFM:
- extract_sectors_from_bitstream_mfm_pc(bitstream, track_size, sectors, sectdata, sizeof(sectdata));
- break;
- }
-
// Check compatibility with every candidate, copy in-place
int *ok_cands = &candidates[0];
- for(unsigned int i=0; i != candidates.size(); i++) {
+ for(unsigned int i=0; i < candidates.size(); i++) {
const format &f = formats[candidates[i]];
- int ns = 0;
- for(int j=0; j<256; j++)
- if(sectors[j].data) {
- int sid;
- if(f.sector_base_id == -1) {
- for(sid=0; sid < f.sector_count; sid++)
- if(f.per_sector_id[sid] == j)
- break;
- } else
- sid = j - f.sector_base_id;
- if(sid < 0 || sid > f.sector_count)
- goto fail;
- if(f.sector_base_size) {
- if(sectors[j].size != f.sector_base_size)
- goto fail;
- } else {
- if(sectors[j].size != f.per_sector_size[sid])
- goto fail;
+ for(int track=0; track < f.track_count; track++) {
+ for(int head=0; head < f.head_count; head++) {
+ uint8_t bitstream[500000/8];
+ uint8_t sectdata[50000];
+ desc_xs sectors[256];
+ int track_size;
+ const format &tf = get_track_format(f, head, track);
+
+ generate_bitstream_from_track(track, head, tf.cell_size, bitstream, track_size, image);
+
+ switch (tf.encoding)
+ {
+ case floppy_image::FM:
+ extract_sectors_from_bitstream_fm_pc(bitstream, track_size, sectors, sectdata, sizeof(sectdata));
+ break;
+ case floppy_image::MFM:
+ extract_sectors_from_bitstream_mfm_pc(bitstream, track_size, sectors, sectdata, sizeof(sectdata));
+ break;
}
- ns++;
+ int ns = 0;
+ for(int j=0; j<256; j++)
+ if(sectors[j].data) {
+ int sid;
+ if(tf.sector_base_id == -1) {
+ for(sid=0; sid < tf.sector_count; sid++)
+ if(tf.per_sector_id[sid] == j)
+ break;
+ } else
+ sid = j - tf.sector_base_id;
+ if(sid < 0 || sid > tf.sector_count)
+ goto fail;
+ if(tf.sector_base_size) {
+ if(sectors[j].size != tf.sector_base_size)
+ goto fail;
+ } else {
+ if(sectors[j].size != tf.per_sector_size[sid])
+ goto fail;
+ }
+ ns++;
+ }
+ if(ns != tf.sector_count)
+ goto fail;
}
- if(ns == f.sector_count)
- *ok_cands++ = candidates[i];
+ }
+ *ok_cands++ = candidates[i];
fail:
;
}
candidates.resize(ok_cands - &candidates[0]);
}
+// A track specific format is to be supplied.
void wd177x_format::extract_sectors(floppy_image *image, const format &f, desc_s *sdesc, int track, int head)
{
uint8_t bitstream[500000/8];