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:
parent
234bef2a88
commit
71ec7624ca
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user