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:
@@ -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"
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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_;
|
||||||
|
Reference in New Issue
Block a user