From 87df951a41d5cfb0376c788007b7d88951d4dff7 Mon Sep 17 00:00:00 2001 From: pnp2084 Date: Thu, 10 Nov 2022 00:59:19 -0800 Subject: Implement FM and mixed FM/MFM reading to DMK disk image format (#10514) --- src/lib/formats/dmk_dsk.cpp | 190 ++++++++++++++++++++++++++++++++++---------- src/lib/formats/dmk_dsk.h | 3 + src/mame/trs/trs80.cpp | 3 +- 3 files changed, 154 insertions(+), 42 deletions(-) diff --git a/src/lib/formats/dmk_dsk.cpp b/src/lib/formats/dmk_dsk.cpp index 6af3a15b5f6..042d19c403a 100644 --- a/src/lib/formats/dmk_dsk.cpp +++ b/src/lib/formats/dmk_dsk.cpp @@ -8,7 +8,6 @@ TODO: - Add write/format support. -- Add single density support. - Check support on other drivers besides msx. *********************************************************************/ @@ -17,6 +16,7 @@ TODO: #include "ioprocs.h" +#include "coretmpl.h" dmk_format::dmk_format() { @@ -83,6 +83,24 @@ int dmk_format::identify(util::random_read &io, uint32_t form_factor, const std: } +uint32_t dmk_format::wide_fm(uint16_t val) +{ + uint32_t res = 0; + for (int i = 15; i >= 0; i--) { + res |= (util::BIT(val, i) << (i*2 + 1)); + } + return res; +} + +uint32_t dmk_format::data_to_wide_fm(uint8_t val) +{ + uint16_t res = 0xaaaa; // clock + for (int i = 7; i >= 0; i--) { + res |= (util::BIT(val, i) << i*2); // data + } + return wide_fm(res); +} + bool dmk_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) const { size_t actual; @@ -95,117 +113,207 @@ bool dmk_format::load(util::random_read &io, uint32_t form_factor, const std::ve const int track_size = ( header[3] << 8 ) | header[2]; const int heads = (header[4] & 0x10) ? 1 : 2; const bool is_sd = (header[4] & 0x40) ? true : false; - //const int raw_track_size = 2 * 8 * ( track_size - 0x80 ); + auto variant = floppy_image::SSDD; if (is_sd) { if (heads == 2) { - image->set_variant(floppy_image::DSSD); + variant = floppy_image::DSSD; } else { - image->set_variant(floppy_image::SSSD); + variant = floppy_image::SSSD; } } else { if (heads == 2) { - image->set_variant(floppy_image::DSDD); + variant = floppy_image::DSDD; } else { - image->set_variant(floppy_image::SSDD); + variant = floppy_image::SSDD; } } + image->set_variant(variant); + + int fm_stride = is_sd ? 1 : 2; for (int track = 0; track < tracks; track++) { for (int head = 0; head < heads; head++) { + int fm_loss = 0; std::vector track_data(track_size); std::vector raw_track_data; + int mark_location[64*2+1]; + uint8_t mark_value[64*2+1]; + bool mark_is_mfm[64*2+1]; int iam_location = -1; - int idam_location[64]; - int dam_location[64]; // Read track io.read_at(header_size + (heads * track + head) * track_size, &track_data[0], track_size, actual); - for (int i = 0; i < 64; i++) + for (int i = 0; i < 64*2+1; i++) { - idam_location[i] = -1; - dam_location[i] = -1; + mark_location[i] = -1; + mark_value[i] = 0xfe; + mark_is_mfm[i] = !is_sd; // Use default encoding } + int mark_count = 0; - // Find IDAM locations + // Find IDAM/DAM locations uint16_t track_header_offset = 0; uint16_t track_offset = ( ( track_data[track_header_offset + 1] << 8 ) | track_data[track_header_offset] ) & 0x3fff; + bool idam_is_mfm = (track_data[track_header_offset + 1] & 0x80) ? true : false; track_header_offset += 2; while ( track_offset != 0 && track_offset >= 0x83 && track_offset < track_size && track_header_offset < 0x80 ) { // Assume 3 bytes before IDAM pointers are the start of IDAM indicators - idam_location[(track_header_offset/2) - 1] = track_offset - 3; + int mark_offset = idam_is_mfm ? 3 : 0; + mark_location[mark_count] = track_offset - mark_offset; + mark_value[mark_count] = 0xfe; + mark_is_mfm[mark_count] = idam_is_mfm; + mark_count++; + int stride = idam_is_mfm ? 1 : fm_stride; // Scan for DAM location - for (int i = track_offset + 53; i > track_offset + 10; i--) + for (int i = track_offset + 10*stride; i < track_offset + 53*stride; i++) { - if ((track_data[i] == 0xfb || track_data[i] == 0xf8) && track_data[i-1] == 0xa1 && track_data[i-2] == 0xa1) + if ((track_data[i] >= 0xf8 && track_data[i] <= 0xfb)) { - dam_location[(track_header_offset/2) - 1] = i - 3; - break; + if (!idam_is_mfm || (track_data[i-1] == 0xa1 && track_data[i-2] == 0xa1)) + { + mark_location[mark_count] = i - mark_offset; + mark_value[mark_count] = track_data[i]; + mark_is_mfm[mark_count] = idam_is_mfm; + mark_count++; + + break; + } } } + idam_is_mfm = (track_data[track_header_offset + 1] & 0x80) ? true : false; track_offset = ( ( track_data[track_header_offset + 1] << 8 ) | track_data[track_header_offset] ) & 0x3fff; track_header_offset += 2; - }; + } + + // Prevent encoding from switching after last sector + if (mark_count > 0) + { + mark_is_mfm[mark_count] = mark_is_mfm[mark_count - 1]; + } // Find IAM location - for(int i = idam_location[0] - 1; i >= 3; i--) + for(int i = mark_location[0] - 1; i >= 3; i--) { // It's usually 3 bytes but several dumped tracks seem to contain only 2 bytes - if (track_data[i] == 0xfc && track_data[i-1] == 0xc2 && track_data[i-2] == 0xc2) + if (track_data[i] == 0xfc && (is_sd || (track_data[i-1] == 0xc2 && track_data[i-2] == 0xc2))) { - iam_location = i - 3; + iam_location = i - (is_sd ? 0 : 3); break; } } - int idam_index = 0; - int dam_index = 0; + int curr_mark = 0; + bool enc_mfm = mark_is_mfm[curr_mark]; for (int offset = 0x80; offset < track_size; offset++) { if (offset == iam_location) { - // Write IAM - raw_w(raw_track_data, 16, 0x5224); - raw_w(raw_track_data, 16, 0x5224); - raw_w(raw_track_data, 16, 0x5224); - offset += 3; + if (!is_sd) + { + // Write IAM + raw_w(raw_track_data, 16, 0x5224); + raw_w(raw_track_data, 16, 0x5224); + raw_w(raw_track_data, 16, 0x5224); + offset += 3; + } + else + { + raw_w(raw_track_data, 32, wide_fm(0xf77a)); // FC clocked with D7 + offset += fm_stride; + } } - if (offset == idam_location[idam_index]) + // If close to mark, switch encoding + if (offset + 8 >= mark_location[curr_mark]) + { + bool new_enc = mark_is_mfm[curr_mark]; + if (new_enc != enc_mfm) + { + enc_mfm = new_enc; + } + } + if (offset == mark_location[curr_mark] + || (!enc_mfm && offset - fm_stride + 1 == mark_location[curr_mark]) + ) { - raw_w(raw_track_data, 16, 0x4489); - raw_w(raw_track_data, 16, 0x4489); - raw_w(raw_track_data, 16, 0x4489); - idam_index += 1; - offset += 3; + if (enc_mfm) + { + raw_w(raw_track_data, 16, 0x4489); + raw_w(raw_track_data, 16, 0x4489); + raw_w(raw_track_data, 16, 0x4489); + offset += 3; + if (fm_stride == 1) + { + fm_loss += 3; + } + } + else + { + uint16_t mark; + switch (mark_value[curr_mark]) + { + default: + case 0xfb: mark = 0xf56f; break; + case 0xfa: mark = 0xf56e; break; + case 0xf9: mark = 0xf56b; break; + case 0xf8: mark = 0xf56a; break; + case 0xfe: mark = 0xf57e; break; + } + raw_w(raw_track_data, 32, wide_fm(mark)); + offset += fm_stride; + } + curr_mark++; } - if (offset == dam_location[dam_index]) + if (enc_mfm) { - raw_w(raw_track_data, 16, 0x4489); - raw_w(raw_track_data, 16, 0x4489); - raw_w(raw_track_data, 16, 0x4489); - dam_index += 1; - offset += 3; + if (fm_stride == 1) + { + fm_loss++; + } + mfm_w(raw_track_data, 8, track_data[offset]); } + else + raw_w(raw_track_data, 32, data_to_wide_fm(track_data[offset])); + + + if (!enc_mfm) + offset += fm_stride - 1; + } - mfm_w(raw_track_data, 8, track_data[offset]); + if (fm_loss != 0) + { + if (enc_mfm) + { + for (int jj = 0; jj < fm_loss; jj++) + { + mfm_w(raw_track_data, 8, 0x4e); + } + } + else + { + for (int jj = 0; jj < fm_loss/2; jj++) + { + raw_w(raw_track_data, 32, data_to_wide_fm(0xff)); + } + } } generate_track_from_levels(track, head, raw_track_data, 0, image); diff --git a/src/lib/formats/dmk_dsk.h b/src/lib/formats/dmk_dsk.h index 873484a8e94..8ab295075fb 100644 --- a/src/lib/formats/dmk_dsk.h +++ b/src/lib/formats/dmk_dsk.h @@ -28,6 +28,9 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; virtual bool supports_save() const override; +protected: + static uint32_t wide_fm(uint16_t val); + static uint32_t data_to_wide_fm(uint8_t val); }; extern const dmk_format FLOPPY_DMK_FORMAT; diff --git a/src/mame/trs/trs80.cpp b/src/mame/trs/trs80.cpp index 8af755ecefb..208fc1e4573 100644 --- a/src/mame/trs/trs80.cpp +++ b/src/mame/trs/trs80.cpp @@ -158,7 +158,7 @@ ht1080z works #include "sound/ay8910.h" #include "softlist_dev.h" #include "utf8.h" - +#include "formats/dmk_dsk.h" void trs80_state::trs80_mem(address_map &map) { @@ -411,6 +411,7 @@ GFXDECODE_END void trs80_state::floppy_formats(format_registration &fr) { + fr.add(FLOPPY_DMK_FORMAT); fr.add(FLOPPY_JV1_FORMAT); } -- cgit v1.2.3