1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-06 01:28:57 +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);
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);
// 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.
uint8_t sector_number_ = 0;
for(std::size_t c = 0; c < 16; ++c) {
segments.push_back(Encodings::AppleGCR::six_and_two_sync(10));
segments.push_back(Encodings::AppleGCR::header(0, track, sector_number_));
segments.push_back(Encodings::AppleGCR::six_and_two_sync(10));
segments.push_back(Encodings::AppleGCR::six_and_two_data(&track_data[c * 256]));
segments.push_back(Encodings::AppleGCR::six_and_two_sync(10));
segment += Encodings::AppleGCR::six_and_two_sync(10);
segment += Encodings::AppleGCR::header(0, track, sector_number_);
segment += Encodings::AppleGCR::six_and_two_sync(10);
segment += Encodings::AppleGCR::six_and_two_data(&track_data[c * 256]);
// 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.
@ -68,13 +67,12 @@ std::shared_ptr<Track> AppleDSK::get_track_at_position(Track::Address address) {
}
// Pad if necessary.
int encoded_length = (80 + 112 + 80 + 2848 + 80) * sectors_per_track_;
if(encoded_length < 50000) {
segments.push_back(Encodings::AppleGCR::six_and_two_sync((50000 - encoded_length) >> 3));
if(segment.number_of_bits < 50000) {
segment += Encodings::AppleGCR::six_and_two_sync((50000 - segment.number_of_bits) >> 3);
}
} 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
// region, then switch back to ordinary behaviour as soon as a
// non-FF appears.
std::vector<Storage::Disk::PCMSegment> segments;
PCMSegment segment;
std::size_t start_index = 0;
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)
segments.push_back(Encodings::AppleGCR::six_and_two_sync(static_cast<int>(start_index)));
if(start_index) {
segment += Encodings::AppleGCR::six_and_two_sync(static_cast<int>(start_index));
}
std::size_t index = start_index;
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>(location));
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.
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;
while(index < track_length && track_data[index] == 0xff)
++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;
}
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() {
// track the initial bit pointer for potentially considering whether this was an
// initial index hole or a subsequent one later on

View File

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