mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
With some refactoring makes some minor steps towards supporting gaps.
This commit is contained in:
parent
f37179d9f2
commit
18b6f17e86
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include "IPF.hpp"
|
#include "IPF.hpp"
|
||||||
|
|
||||||
#include "../../Track/PCMTrack.hpp"
|
|
||||||
#include "../../Encodings/MFM/Encoder.hpp"
|
#include "../../Encodings/MFM/Encoder.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -258,19 +257,22 @@ std::shared_ptr<Track> IPF::get_track_at_position([[maybe_unused]] Track::Addres
|
|||||||
} type = Type(gap_header & 0x1f);
|
} type = Type(gap_header & 0x1f);
|
||||||
const size_t length = block_size(file_, gap_header);
|
const size_t length = block_size(file_, gap_header);
|
||||||
|
|
||||||
// TODO: write the gap.
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case Type::GapLength:
|
case Type::GapLength:
|
||||||
printf("Unhandled gap length %zu bytes\n", length);
|
printf("Adding gap length %zu bits\n", length);
|
||||||
|
add_gap(segments, length_of_a_bit, length, block.default_gap_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case Type::SampleLength:
|
case Type::SampleLength:
|
||||||
printf("Unhandled sampled gap length %zu bytes\n", length);
|
printf("Adding sampled gap length %zu bits\n", length);
|
||||||
file_.seek(long(length >> 3), SEEK_CUR);
|
add_raw_data(segments, length_of_a_bit, length);
|
||||||
|
// file_.seek(long(length >> 3), SEEK_CUR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if(block.gap_bits) {
|
||||||
|
add_gap(segments, length_of_a_bit, block.gap_bits, block.default_gap_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(block.data_offset) {
|
if(block.data_offset) {
|
||||||
@ -288,65 +290,16 @@ std::shared_ptr<Track> IPF::get_track_at_position([[maybe_unused]] Track::Addres
|
|||||||
const auto next_chunk = file_.tell() + long(length >> 3);
|
const auto next_chunk = file_.tell() + long(length >> 3);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: write the data.
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
/*case Type::Gap: {
|
|
||||||
auto &segment = segments.emplace_back();
|
|
||||||
segment.length_of_a_bit = length_of_a_bit;
|
|
||||||
segment.data.reserve(size_t(length + 31) & size_t(~31));
|
|
||||||
auto encoder = Storage::Encodings::MFM::GetMFMEncoder(segment.data);
|
|
||||||
while(segment.data.size() < length) {
|
|
||||||
encoder->add_byte(uint8_t(block.default_gap_value >> 24));
|
|
||||||
encoder->add_byte(uint8_t(block.default_gap_value >> 16));
|
|
||||||
encoder->add_byte(uint8_t(block.default_gap_value >> 8));
|
|
||||||
encoder->add_byte(uint8_t(block.default_gap_value >> 0));
|
|
||||||
}
|
|
||||||
segment.data.resize(length);
|
|
||||||
} break;*/
|
|
||||||
|
|
||||||
case Type::Gap:
|
case Type::Gap:
|
||||||
case Type::Data: {
|
case Type::Data:
|
||||||
printf("Handling data type %d, length %zu bits\n", int(type), length);
|
add_unencoded_data(segments, length_of_a_bit, length);
|
||||||
auto &segment = segments.emplace_back();
|
break;
|
||||||
segment.length_of_a_bit = length_of_a_bit;
|
|
||||||
|
|
||||||
// Length appears to be in pre-encoded bits; double that to get encoded bits.
|
|
||||||
const auto byte_length = (length + 7) >> 3;
|
|
||||||
segment.data.reserve(byte_length * 16);
|
|
||||||
|
|
||||||
auto encoder = Storage::Encodings::MFM::GetMFMEncoder(segment.data);
|
|
||||||
for(size_t c = 0; c < length; c += 8) {
|
|
||||||
encoder->add_byte(file_.get8());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(segment.data.size() <= (byte_length * 16));
|
|
||||||
segment.data.resize(length * 2);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case Type::Sync:
|
case Type::Sync:
|
||||||
case Type::Raw: {
|
case Type::Raw:
|
||||||
printf("Handling data type %d, length %zu bits\n", int(type), length);
|
add_raw_data(segments, length_of_a_bit, length);
|
||||||
auto &segment = segments.emplace_back();
|
break;
|
||||||
segment.length_of_a_bit = length_of_a_bit;
|
|
||||||
|
|
||||||
const auto bit_length = size_t(length + 7) & size_t(~7);
|
|
||||||
segment.data.reserve(bit_length);
|
|
||||||
|
|
||||||
for(size_t bit = 0; bit < length; bit += 8) {
|
|
||||||
const uint8_t next = file_.get8();
|
|
||||||
segment.data.push_back(next & 0x80);
|
|
||||||
segment.data.push_back(next & 0x40);
|
|
||||||
segment.data.push_back(next & 0x20);
|
|
||||||
segment.data.push_back(next & 0x10);
|
|
||||||
segment.data.push_back(next & 0x08);
|
|
||||||
segment.data.push_back(next & 0x04);
|
|
||||||
segment.data.push_back(next & 0x02);
|
|
||||||
segment.data.push_back(next & 0x01);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(segment.data.size() <= bit_length);
|
|
||||||
segment.data.resize(length);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Unhandled data type %d, length %zu bits\n", int(type), length);
|
printf("Unhandled data type %d, length %zu bits\n", int(type), length);
|
||||||
@ -424,3 +377,61 @@ Storage::Time IPF::bit_length(TrackDescription::Density density, int block) {
|
|||||||
|
|
||||||
return us200; // i.e. default to 2µs.
|
return us200; // i.e. default to 2µs.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IPF::add_gap(std::vector<Storage::Disk::PCMSegment> &track, Time bit_length, size_t num_bits, uint32_t value) {
|
||||||
|
auto &segment = track.emplace_back();
|
||||||
|
segment.length_of_a_bit = bit_length;
|
||||||
|
|
||||||
|
// Empirically, I think gaps require MFM encoding.
|
||||||
|
const auto byte_length = (num_bits + 7) >> 3;
|
||||||
|
segment.data.reserve(byte_length * 16);
|
||||||
|
|
||||||
|
auto encoder = Storage::Encodings::MFM::GetMFMEncoder(segment.data);
|
||||||
|
while(segment.data.size() < num_bits) {
|
||||||
|
encoder->add_byte(uint8_t(value >> 24));
|
||||||
|
value = (value << 8) | (value >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(segment.data.size() <= (byte_length * 16));
|
||||||
|
segment.data.resize(num_bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPF::add_unencoded_data(std::vector<Storage::Disk::PCMSegment> &track, Time bit_length, size_t num_bits) {
|
||||||
|
auto &segment = track.emplace_back();
|
||||||
|
segment.length_of_a_bit = bit_length;
|
||||||
|
|
||||||
|
// Length appears to be in pre-encoded bits; double that to get encoded bits.
|
||||||
|
const auto byte_length = (num_bits + 7) >> 3;
|
||||||
|
segment.data.reserve(num_bits * 16);
|
||||||
|
|
||||||
|
auto encoder = Storage::Encodings::MFM::GetMFMEncoder(segment.data);
|
||||||
|
for(size_t c = 0; c < num_bits; c += 8) {
|
||||||
|
encoder->add_byte(file_.get8());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(segment.data.size() <= (byte_length * 16));
|
||||||
|
segment.data.resize(num_bits * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPF::add_raw_data(std::vector<Storage::Disk::PCMSegment> &track, Time bit_length, size_t num_bits) {
|
||||||
|
auto &segment = track.emplace_back();
|
||||||
|
segment.length_of_a_bit = bit_length;
|
||||||
|
|
||||||
|
const auto num_bits_ceiling = size_t(num_bits + 7) & size_t(~7);
|
||||||
|
segment.data.reserve(num_bits_ceiling);
|
||||||
|
|
||||||
|
for(size_t bit = 0; bit < num_bits; bit += 8) {
|
||||||
|
const uint8_t next = file_.get8();
|
||||||
|
segment.data.push_back(next & 0x80);
|
||||||
|
segment.data.push_back(next & 0x40);
|
||||||
|
segment.data.push_back(next & 0x20);
|
||||||
|
segment.data.push_back(next & 0x10);
|
||||||
|
segment.data.push_back(next & 0x08);
|
||||||
|
segment.data.push_back(next & 0x04);
|
||||||
|
segment.data.push_back(next & 0x02);
|
||||||
|
segment.data.push_back(next & 0x01);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(segment.data.size() <= num_bits_ceiling);
|
||||||
|
segment.data.resize(num_bits);
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define IPF_hpp
|
#define IPF_hpp
|
||||||
|
|
||||||
#include "../DiskImage.hpp"
|
#include "../DiskImage.hpp"
|
||||||
|
#include "../../Track/PCMTrack.hpp"
|
||||||
#include "../../../FileHolder.hpp"
|
#include "../../../FileHolder.hpp"
|
||||||
#include "../../../TargetPlatforms.hpp"
|
#include "../../../TargetPlatforms.hpp"
|
||||||
|
|
||||||
@ -68,8 +69,6 @@ class IPF: public DiskImage, public TargetPlatform::TypeDistinguisher {
|
|||||||
bool has_fuzzy_bits = false;
|
bool has_fuzzy_bits = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Time bit_length(TrackDescription::Density, int block);
|
|
||||||
|
|
||||||
int head_count_;
|
int head_count_;
|
||||||
int track_count_;
|
int track_count_;
|
||||||
std::map<Track::Address, TrackDescription> tracks_;
|
std::map<Track::Address, TrackDescription> tracks_;
|
||||||
@ -79,6 +78,11 @@ class IPF: public DiskImage, public TargetPlatform::TypeDistinguisher {
|
|||||||
return TargetPlatform::Type(platform_type_);
|
return TargetPlatform::Type(platform_type_);
|
||||||
}
|
}
|
||||||
TargetPlatform::IntType platform_type_ = TargetPlatform::Amiga;
|
TargetPlatform::IntType platform_type_ = TargetPlatform::Amiga;
|
||||||
|
|
||||||
|
Time bit_length(TrackDescription::Density, int block);
|
||||||
|
void add_gap(std::vector<Storage::Disk::PCMSegment> &, Time bit_length, size_t num_bits, uint32_t value);
|
||||||
|
void add_unencoded_data(std::vector<Storage::Disk::PCMSegment> &, Time bit_length, size_t num_bits);
|
||||||
|
void add_raw_data(std::vector<Storage::Disk::PCMSegment> &, Time bit_length, size_t num_bits);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user