From 2f86b07cfa2535c2e527f4a0d6b6577a9a5f1cc7 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 26 Nov 2016 13:40:10 +0800 Subject: [PATCH] Added a parser for Oric-format MFM disks. Causing my first disk to load! --- Storage/Disk/Formats/OricMFMDSK.cpp | 61 +++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/Storage/Disk/Formats/OricMFMDSK.cpp b/Storage/Disk/Formats/OricMFMDSK.cpp index c522e092f..59b4b2b10 100644 --- a/Storage/Disk/Formats/OricMFMDSK.cpp +++ b/Storage/Disk/Formats/OricMFMDSK.cpp @@ -8,6 +8,7 @@ #include "OricMFMDSK.hpp" #include "../PCMTrack.hpp" +#include "../Encodings/MFM.hpp" using namespace Storage::Disk; @@ -37,26 +38,64 @@ unsigned int OricMFMDSK::get_head_count() std::shared_ptr OricMFMDSK::get_track_at_position(unsigned int head, unsigned int position) { - long offset = 0; + long seek_offset = 0; switch(geometry_type_) { case 1: - offset = (head * track_count_) + position; + seek_offset = (head * track_count_) + position; break; case 2: - offset = (position * track_count_ * head_count_) + head; + seek_offset = (position * track_count_ * head_count_) + head; break; } - fseek(file_, (offset * 6400) + 256, SEEK_SET); - - // TODO: upon review, the file format actually seems to omit clock bits. So it's not an MFM capture. - // A consumer must contextually guess when an FB, FC, etc is meant to be a control mark. So turfing - // the data over directly as below isn't correct. + fseek(file_, (seek_offset * 6400) + 256, SEEK_SET); PCMSegment segment; - segment.number_of_bits = 6250*8; - segment.data.resize(6250); - fread(segment.data.data(), 1, 6250, file_); + + // The file format omits clock bits. So it's not a genuine MFM capture. + // A consumer must contextually guess when an FB, FC, etc is meant to be a control mark. + size_t track_offset = 0; + uint8_t last_header[6]; + std::unique_ptr encoder = Encodings::MFM::GetMFMEncoder(segment.data); + while(track_offset < 6250) + { + uint8_t next_byte = (uint8_t)fgetc(file_); + track_offset++; + + switch(next_byte) + { + default: + encoder->add_byte(next_byte); + break; + + case 0xfe: // an ID synchronisation + { + encoder->add_ID_address_mark(); + + for(int byte = 0; byte < 6; byte++) + { + last_header[byte] = (uint8_t)fgetc(file_); + encoder->add_byte(last_header[byte]); + track_offset++; + if(track_offset == 6250) break; + } + } + break; + + case 0xfb: // a data synchronisation + encoder->add_data_address_mark(); + + for(int byte = 0; byte < (128 << last_header[3]) + 2; byte++) + { + encoder->add_byte((uint8_t)fgetc(file_)); + track_offset++; + if(track_offset == 6250) break; + } + break; + } + } + + segment.number_of_bits = (unsigned int)(segment.data.size() * 8); std::shared_ptr track(new PCMTrack(segment)); return track;