mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Merge pull request #535 from TomHarte/DSKFixes
Corrects Apple DSK track length, inter-track skew, and Pro-DOS volume number.
This commit is contained in:
commit
f639cdc8ad
@ -75,19 +75,24 @@ std::shared_ptr<Track> AppleDSK::get_track_at_position(Track::Address address) {
|
||||
// In either case below, the code aims for exactly 50,000 bits per track.
|
||||
if(sectors_per_track_ == 16) {
|
||||
// Write gap 1.
|
||||
segment += Encodings::AppleGCR::six_and_two_sync(16);
|
||||
segment += Encodings::AppleGCR::six_and_two_sync(24);
|
||||
|
||||
// Write the sectors.
|
||||
for(uint8_t c = 0; c < 16; ++c) {
|
||||
segment += Encodings::AppleGCR::header(254, track, c);
|
||||
segment += Encodings::AppleGCR::header(is_prodos_ ? 0x01 : 0xfe, track, c); // Volume number is 0xfe for DOS 3.3, 0x01 for Pro-DOS.
|
||||
segment += Encodings::AppleGCR::six_and_two_sync(7); // Gap 2: 7 sync words.
|
||||
segment += Encodings::AppleGCR::six_and_two_data(&track_data[logical_sector_for_physical_sector(c) * 256]);
|
||||
segment += Encodings::AppleGCR::six_and_two_sync(16); // Gap 3: 16 sync words.
|
||||
segment += Encodings::AppleGCR::six_and_two_sync(20); // Gap 3: 20 sync words.
|
||||
}
|
||||
} else {
|
||||
// TODO: 5 and 3, 13-sector format. If DSK actually supports it?
|
||||
}
|
||||
|
||||
// Apply inter-track skew; skew is about 40ms between each track; assuming 300RPM that's
|
||||
// 1/5th of a revolution.
|
||||
const size_t offset_in_fifths = address.position.as_int() % 5;
|
||||
segment.rotate_right(offset_in_fifths * segment.data.size() / 5);
|
||||
|
||||
return std::make_shared<PCMTrack>(segment);
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,25 @@ PCMSegment &PCMSegment::operator +=(const PCMSegment &rhs) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void PCMSegment::rotate_right(size_t length) {
|
||||
length %= data.size();
|
||||
if(!length) return;
|
||||
|
||||
// To rotate to the right, front-insert the proper number
|
||||
// of bits from the end and then resize. To rotate to
|
||||
// the left, do the opposite.
|
||||
std::vector<uint8_t> data_copy;
|
||||
if(length > 0) {
|
||||
data_copy.insert(data_copy.end(), data.end() - static_cast<off_t>(length), data.end());
|
||||
data.erase(data.end() - static_cast<off_t>(length), data.end());
|
||||
data.insert(data.begin(), data_copy.begin(), data_copy.end());
|
||||
} else {
|
||||
data_copy.insert(data_copy.end(), data.begin(), data.begin() - static_cast<off_t>(length));
|
||||
data.erase(data.begin(), data.begin() - static_cast<off_t>(length));
|
||||
data.insert(data.end(), data_copy.begin(), data_copy.end());
|
||||
}
|
||||
}
|
||||
|
||||
Storage::Disk::Track::Event PCMSegmentEventSource::get_next_event() {
|
||||
// track the initial bit pointer for potentially considering whether this was an
|
||||
// initial index hole or a subsequent one later on
|
||||
|
@ -105,6 +105,13 @@ struct PCMSegment {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
Rotates all bits in this segment by @c length bits.
|
||||
|
||||
@c length is signed; to rotate left provide a negative number.
|
||||
*/
|
||||
void rotate_right(size_t length);
|
||||
|
||||
/*!
|
||||
Produces a byte buffer where the contents of @c data are serialised into bytes
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user