mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-07 20:30:52 +00:00
Adds better support for WD-esque false sync, improves STX track patching.
This commit is contained in:
parent
fab35b360a
commit
1f539822ee
@ -67,7 +67,7 @@
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Release"
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
enableASanStackUseAfterReturn = "YES"
|
||||
|
@ -83,6 +83,7 @@ class TrackConstructor {
|
||||
using Shifter = Storage::Encodings::MFM::Shifter;
|
||||
Shifter shifter;
|
||||
shifter.set_should_obey_syncs(true);
|
||||
shifter.set_is_double_density(true);
|
||||
|
||||
// Add whatever comes from the track.
|
||||
for(auto bit: segment.data) {
|
||||
@ -127,8 +128,7 @@ class TrackConstructor {
|
||||
// To reconcile the list of sectors with the WD get track-style track image,
|
||||
// use sector bodies as definitive and refer to the track image for in-fill.
|
||||
auto track_position = track_data_.begin();
|
||||
const auto address_mark = {0xa1, 0xa1, 0xfe};
|
||||
const auto track_mark = {0xa1, 0xa1, 0xfb};
|
||||
const auto sync_mark = {0xa1, 0xa1};
|
||||
struct Location {
|
||||
enum Type {
|
||||
Address, Data
|
||||
@ -148,15 +148,16 @@ class TrackConstructor {
|
||||
// the next thing that looks like a header of any sort.
|
||||
auto address_position = std::search(track_position, track_data_.end(), track_address.begin(), track_address.end());
|
||||
if(address_position == track_data_.end()) {
|
||||
address_position = std::search(track_position, track_data_.end(), address_mark.begin(), address_mark.end());
|
||||
address_position = std::search(track_position, track_data_.end(), sync_mark.begin(), sync_mark.end());
|
||||
}
|
||||
|
||||
// Stop now if there's nowhere obvious to put this sector.
|
||||
if(address_position == track_data_.end()) break;
|
||||
locations.emplace_back(Location::Address, address_position, sector);
|
||||
// Place this address only if somewhere to put it was found.
|
||||
if(address_position != track_data_.end()) {
|
||||
locations.emplace_back(Location::Address, address_position, sector);
|
||||
|
||||
// Advance the track position.
|
||||
track_position = address_position;
|
||||
// Advance the track position.
|
||||
track_position = address_position;
|
||||
}
|
||||
}
|
||||
|
||||
// Do much the same thing for the data, if it exists.
|
||||
@ -165,9 +166,12 @@ class TrackConstructor {
|
||||
|
||||
auto data_position = std::search(track_position, track_data_.end(), track_data.begin(), track_data.end());
|
||||
if(data_position == track_data_.end()) {
|
||||
data_position = std::search(track_position, track_data_.end(), track_mark.begin(), track_mark.end());
|
||||
data_position = std::search(track_position, track_data_.end(), sync_mark.begin(), sync_mark.end());
|
||||
}
|
||||
if(data_position == track_data_.end()) {
|
||||
// Desperation: guess from the given offset.
|
||||
data_position = track_data_.begin() + (sector.bit_position / 16);
|
||||
}
|
||||
if(data_position == track_data_.end()) break;
|
||||
|
||||
locations.emplace_back(Location::Data, data_position, sector);
|
||||
track_position = data_position;
|
||||
|
@ -25,7 +25,7 @@ void Shifter::set_should_obey_syncs(bool should_obey_syncs) {
|
||||
|
||||
void Shifter::add_input_bit(int value) {
|
||||
shift_register_ = (shift_register_ << 1) | static_cast<unsigned int>(value);
|
||||
bits_since_token_++;
|
||||
++bits_since_token_;
|
||||
|
||||
token_ = Token::None;
|
||||
if(should_obey_syncs_) {
|
||||
@ -57,6 +57,20 @@ void Shifter::add_input_bit(int value) {
|
||||
} else {
|
||||
switch(shift_register_ & 0xffff) {
|
||||
case Storage::Encodings::MFM::MFMIndexSync:
|
||||
// This models a bit of slightly weird WD behaviour;
|
||||
// if an index sync was detected where it wasn't expected,
|
||||
// the WD will resync but also may return the clock bits
|
||||
// rather than data bits as the next byte read, depending
|
||||
// on framing.
|
||||
//
|
||||
// TODO: make this optional, if ever a Shifter with
|
||||
// well-defined non-WD behaviour is needed.
|
||||
//
|
||||
// TODO: Verify WD behaviour.
|
||||
if(bits_since_token_&1) {
|
||||
shift_register_ >>= 1;
|
||||
}
|
||||
|
||||
bits_since_token_ = 0;
|
||||
is_awaiting_marker_value_ = true;
|
||||
|
||||
|
@ -27,6 +27,10 @@ namespace MFM {
|
||||
It will ordinarily honour sync patterns; that should be turned off when within
|
||||
a sector because false syncs can occur. See @c set_should_obey_syncs.
|
||||
|
||||
It aims to implement the same behaviour as WD177x-series controllers when
|
||||
detecting a false sync — the received byte value will be either a 0xc1 or 0x14,
|
||||
depending on phase.
|
||||
|
||||
Bits should be fed in with @c add_input_bit.
|
||||
|
||||
The current output token can be read with @c get_token. It will usually be None but
|
||||
@ -62,14 +66,14 @@ class Shifter {
|
||||
}
|
||||
|
||||
private:
|
||||
// Bit stream input state
|
||||
// Bit stream input state.
|
||||
int bits_since_token_ = 0;
|
||||
unsigned int shift_register_ = 0;
|
||||
bool is_awaiting_marker_value_ = false;
|
||||
bool should_obey_syncs_ = true;
|
||||
Token token_ = None;
|
||||
|
||||
// input configuration
|
||||
// Input configuration.
|
||||
bool is_double_density_ = false;
|
||||
|
||||
std::unique_ptr<CRC::CCITT> owned_crc_generator_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user