1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-09 21:29:53 +00:00

Switches to producing a single segment for NIBs and DSKs.

I've now seemingly verified that the values read back by the CPU are those I'm intending to produce, so I'm at a loss.
This commit is contained in:
Thomas Harte 2018-05-01 20:31:42 -04:00
parent 05e31d7594
commit 5e34c1b6b8
4 changed files with 47 additions and 16 deletions

View File

@ -47,7 +47,7 @@ std::shared_ptr<Track> AppleDSK::get_track_at_position(Track::Address address) {
file_.seek(file_offset, SEEK_SET); file_.seek(file_offset, SEEK_SET);
const std::vector<uint8_t> track_data = file_.read(static_cast<size_t>(bytes_per_sector * sectors_per_track_)); const std::vector<uint8_t> track_data = file_.read(static_cast<size_t>(bytes_per_sector * sectors_per_track_));
std::vector<Storage::Disk::PCMSegment> segments; Storage::Disk::PCMSegment segment;
const uint8_t track = static_cast<uint8_t>(address.position >> 2); const uint8_t track = static_cast<uint8_t>(address.position >> 2);
// 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.
@ -55,11 +55,10 @@ std::shared_ptr<Track> AppleDSK::get_track_at_position(Track::Address address) {
// Write the sectors. // Write the sectors.
uint8_t sector_number_ = 0; uint8_t sector_number_ = 0;
for(std::size_t c = 0; c < 16; ++c) { for(std::size_t c = 0; c < 16; ++c) {
segments.push_back(Encodings::AppleGCR::six_and_two_sync(10)); segment += Encodings::AppleGCR::six_and_two_sync(10);
segments.push_back(Encodings::AppleGCR::header(0, track, sector_number_)); segment += Encodings::AppleGCR::header(0, track, sector_number_);
segments.push_back(Encodings::AppleGCR::six_and_two_sync(10)); segment += Encodings::AppleGCR::six_and_two_sync(10);
segments.push_back(Encodings::AppleGCR::six_and_two_data(&track_data[c * 256])); segment += Encodings::AppleGCR::six_and_two_data(&track_data[c * 256]);
segments.push_back(Encodings::AppleGCR::six_and_two_sync(10));
// DOS and Pro DOS interleave sectors on disk, and they're represented in a disk // DOS and Pro DOS interleave sectors on disk, and they're represented in a disk
// image in physical order rather than logical. So that skew needs to be applied here. // image in physical order rather than logical. So that skew needs to be applied here.
@ -68,13 +67,12 @@ std::shared_ptr<Track> AppleDSK::get_track_at_position(Track::Address address) {
} }
// Pad if necessary. // Pad if necessary.
int encoded_length = (80 + 112 + 80 + 2848 + 80) * sectors_per_track_; if(segment.number_of_bits < 50000) {
if(encoded_length < 50000) { segment += Encodings::AppleGCR::six_and_two_sync((50000 - segment.number_of_bits) >> 3);
segments.push_back(Encodings::AppleGCR::six_and_two_sync((50000 - encoded_length) >> 3));
} }
} else { } else {
} }
return std::shared_ptr<PCMTrack>(new PCMTrack(segments)); return std::make_shared<PCMTrack>(segment);
} }

View File

@ -50,7 +50,7 @@ std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Di
// tracks and headers), then treat all following FFs as a sync // tracks and headers), then treat all following FFs as a sync
// region, then switch back to ordinary behaviour as soon as a // region, then switch back to ordinary behaviour as soon as a
// non-FF appears. // non-FF appears.
std::vector<Storage::Disk::PCMSegment> segments; PCMSegment segment;
std::size_t start_index = 0; std::size_t start_index = 0;
std::set<size_t> sync_starts; std::set<size_t> sync_starts;
@ -74,8 +74,9 @@ std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Di
} }
} }
if(start_index) if(start_index) {
segments.push_back(Encodings::AppleGCR::six_and_two_sync(static_cast<int>(start_index))); segment += Encodings::AppleGCR::six_and_two_sync(static_cast<int>(start_index));
}
std::size_t index = start_index; std::size_t index = start_index;
for(const auto &location: sync_starts) { for(const auto &location: sync_starts) {
@ -86,7 +87,7 @@ std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Di
track_data.begin() + static_cast<off_t>(index), track_data.begin() + static_cast<off_t>(index),
track_data.begin() + static_cast<off_t>(location)); track_data.begin() + static_cast<off_t>(location));
data_segment.number_of_bits = static_cast<unsigned int>(data_segment.data.size() * 8); data_segment.number_of_bits = static_cast<unsigned int>(data_segment.data.size() * 8);
segments.push_back(std::move(data_segment)); segment += data_segment;
// Add a sync from sync_start to end of 0xffs. // Add a sync from sync_start to end of 0xffs.
if(location == track_length-1) break; if(location == track_length-1) break;
@ -94,8 +95,8 @@ std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Di
index = location; index = location;
while(index < track_length && track_data[index] == 0xff) while(index < track_length && track_data[index] == 0xff)
++index; ++index;
segments.push_back(Encodings::AppleGCR::six_and_two_sync(static_cast<int>(index - location))); segment += Encodings::AppleGCR::six_and_two_sync(static_cast<int>(index - location));
} }
return std::shared_ptr<PCMTrack>(new PCMTrack(segments)); return std::make_shared<PCMTrack>(segment);
} }

View File

@ -43,6 +43,36 @@ void PCMSegmentEventSource::reset() {
next_event_.type = Track::Event::FluxTransition; next_event_.type = Track::Event::FluxTransition;
} }
PCMSegment &PCMSegment::operator +=(const PCMSegment &rhs) {
if(!rhs.number_of_bits) return *this;
if(number_of_bits&7) {
auto target_number_of_bits = number_of_bits + rhs.number_of_bits;
data.resize((target_number_of_bits + 7) >> 3);
std::size_t first_byte = number_of_bits >> 3;
int shift = number_of_bits&7;
data[first_byte] |= rhs.data[0] >> shift;
for(std::size_t target = first_byte+1; target < (data.size()-1); ++target) {
data[target] =
static_cast<uint8_t>(
(rhs.data[target - first_byte - 1] << (8 - shift)) |
(rhs.data[target - first_byte] >> shift)
);
}
data.back() = static_cast<uint8_t>(rhs.data.back() << (8 - shift));
number_of_bits = target_number_of_bits;
} else {
data.insert(data.end(), rhs.data.begin(), rhs.data.end());
number_of_bits += rhs.number_of_bits;
}
return *this;
}
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

@ -41,6 +41,8 @@ struct PCMSegment {
number_of_bits = 0; number_of_bits = 0;
data.clear(); data.clear();
} }
PCMSegment &operator +=(const PCMSegment &rhs);
}; };
/*! /*!