1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-26 09:29:45 +00:00

Corrects Apple DSK track length, inter-track skew, and Pro-DOS volume number.

This commit is contained in:
Thomas Harte 2018-08-27 20:56:25 -04:00
parent 234bef2a88
commit 71ec7624ca
3 changed files with 34 additions and 3 deletions

View File

@ -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. // In either case below, the code aims for exactly 50,000 bits per track.
if(sectors_per_track_ == 16) { if(sectors_per_track_ == 16) {
// Write gap 1. // Write gap 1.
segment += Encodings::AppleGCR::six_and_two_sync(16); segment += Encodings::AppleGCR::six_and_two_sync(24);
// Write the sectors. // Write the sectors.
for(uint8_t c = 0; c < 16; ++c) { 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_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_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 { } else {
// TODO: 5 and 3, 13-sector format. If DSK actually supports it? // 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); return std::make_shared<PCMTrack>(segment);
} }

View File

@ -50,6 +50,25 @@ PCMSegment &PCMSegment::operator +=(const PCMSegment &rhs) {
return *this; 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() { Storage::Disk::Track::Event PCMSegmentEventSource::get_next_event() {
// track the initial bit pointer for potentially considering whether this was an // track the initial bit pointer for potentially considering whether this was an
// initial index hole or a subsequent one later on // initial index hole or a subsequent one later on

View File

@ -105,6 +105,13 @@ struct PCMSegment {
data.clear(); 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 Produces a byte buffer where the contents of @c data are serialised into bytes