1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-07 23:25:00 +00:00

Adds better support for WD-esque false sync, improves STX track patching.

This commit is contained in:
Thomas Harte
2020-01-13 22:19:48 -05:00
parent fab35b360a
commit 1f539822ee
4 changed files with 36 additions and 14 deletions

View File

@@ -67,7 +67,7 @@
</Testables> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Release" buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES" enableASanStackUseAfterReturn = "YES"

View File

@@ -83,6 +83,7 @@ class TrackConstructor {
using Shifter = Storage::Encodings::MFM::Shifter; using Shifter = Storage::Encodings::MFM::Shifter;
Shifter shifter; Shifter shifter;
shifter.set_should_obey_syncs(true); shifter.set_should_obey_syncs(true);
shifter.set_is_double_density(true);
// Add whatever comes from the track. // Add whatever comes from the track.
for(auto bit: segment.data) { 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, // 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. // use sector bodies as definitive and refer to the track image for in-fill.
auto track_position = track_data_.begin(); auto track_position = track_data_.begin();
const auto address_mark = {0xa1, 0xa1, 0xfe}; const auto sync_mark = {0xa1, 0xa1};
const auto track_mark = {0xa1, 0xa1, 0xfb};
struct Location { struct Location {
enum Type { enum Type {
Address, Data Address, Data
@@ -148,15 +148,16 @@ class TrackConstructor {
// the next thing that looks like a header of any sort. // 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()); auto address_position = std::search(track_position, track_data_.end(), track_address.begin(), track_address.end());
if(address_position == track_data_.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. // Place this address only if somewhere to put it was found.
if(address_position == track_data_.end()) break; if(address_position != track_data_.end()) {
locations.emplace_back(Location::Address, address_position, sector); locations.emplace_back(Location::Address, address_position, sector);
// Advance the track position. // Advance the track position.
track_position = address_position; track_position = address_position;
}
} }
// Do much the same thing for the data, if it exists. // 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()); auto data_position = std::search(track_position, track_data_.end(), track_data.begin(), track_data.end());
if(data_position == 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); locations.emplace_back(Location::Data, data_position, sector);
track_position = data_position; track_position = data_position;

View File

@@ -25,7 +25,7 @@ void Shifter::set_should_obey_syncs(bool should_obey_syncs) {
void Shifter::add_input_bit(int value) { void Shifter::add_input_bit(int value) {
shift_register_ = (shift_register_ << 1) | static_cast<unsigned int>(value); shift_register_ = (shift_register_ << 1) | static_cast<unsigned int>(value);
bits_since_token_++; ++bits_since_token_;
token_ = Token::None; token_ = Token::None;
if(should_obey_syncs_) { if(should_obey_syncs_) {
@@ -57,6 +57,20 @@ void Shifter::add_input_bit(int value) {
} else { } else {
switch(shift_register_ & 0xffff) { switch(shift_register_ & 0xffff) {
case Storage::Encodings::MFM::MFMIndexSync: 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; bits_since_token_ = 0;
is_awaiting_marker_value_ = true; is_awaiting_marker_value_ = true;

View File

@@ -27,6 +27,10 @@ namespace MFM {
It will ordinarily honour sync patterns; that should be turned off when within 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. 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. 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 The current output token can be read with @c get_token. It will usually be None but
@@ -62,14 +66,14 @@ class Shifter {
} }
private: private:
// Bit stream input state // Bit stream input state.
int bits_since_token_ = 0; int bits_since_token_ = 0;
unsigned int shift_register_ = 0; unsigned int shift_register_ = 0;
bool is_awaiting_marker_value_ = false; bool is_awaiting_marker_value_ = false;
bool should_obey_syncs_ = true; bool should_obey_syncs_ = true;
Token token_ = None; Token token_ = None;
// input configuration // Input configuration.
bool is_double_density_ = false; bool is_double_density_ = false;
std::unique_ptr<CRC::CCITT> owned_crc_generator_; std::unique_ptr<CRC::CCITT> owned_crc_generator_;