mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-28 06:29:37 +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:
parent
05e31d7594
commit
5e34c1b6b8
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -41,6 +41,8 @@ struct PCMSegment {
|
|||||||
number_of_bits = 0;
|
number_of_bits = 0;
|
||||||
data.clear();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PCMSegment &operator +=(const PCMSegment &rhs);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user