21 data.assign(size, 0x4e);
26 assert(idx < data.size());
27 assert(idam.empty() || (idx > idam.back()));
37 if ((it ==
end(idam)) || (*it != i2)) {
42 if ((it !=
end(idam)) && (*it == i2)) {
49std::optional<RawTrack::Sector> RawTrack::decodeSectorImpl(
int idx)
const
54 if (
read(idx) != 0xFE)
return {};
60 addrCrc.init({0xA1, 0xA1, 0xA1, 0xFE});
62 sector.track =
read(idx++);
63 sector.head =
read(idx++);
64 sector.sector =
read(idx++);
65 sector.sizeCode =
read(idx++);
66 uint8_t addrCrc1 =
read(idx++);
67 uint8_t addrCrc2 =
read(idx++);
68 sector.addrCrcErr = (256 * addrCrc1 + addrCrc2) != addrCrc.getValue();
71 sector.deleted =
false;
72 sector.dataCrcErr =
true;
74 if (!sector.addrCrcErr) {
77 for (
auto i :
xrange(43)) {
81 if (
read(idx2 + j) != 0xA1)
break;
85 uint8_t type =
read(idx2 + 3);
86 if (type !=
one_of(0xfb, 0xf8))
continue;
89 dataCrc.init({0xA1, 0xA1, 0xA1});
93 int dataIdx = idx2 + 4;
94 int sectorSize = 128 << (sector.sizeCode & 7);
96 uint8_t dataCrc1 =
read(dataIdx + sectorSize + 0);
97 uint8_t dataCrc2 =
read(dataIdx + sectorSize + 1);
98 bool dataCrcErr = (256 * dataCrc1 + dataCrc2) != dataCrc.getValue();
101 sector.dataIdx = dataIdx;
102 sector.deleted = type == 0xf8;
103 sector.dataCrcErr = dataCrcErr;
113 std::vector<Sector> result;
114 for (
const auto& i : idam) {
115 if (
auto sector = decodeSectorImpl(narrow<int>(i));
116 sector && (sector->dataIdx != -1)) {
117 result.push_back(*sector);
123static std::vector<unsigned> rotateIdam(std::vector<unsigned> idam,
unsigned startIdx)
128 std::rotate(
begin(idam), it,
end(idam));
135 for (
const auto& i : rotateIdam(idam, startIdx)) {
136 if (
auto sector = decodeSectorImpl(narrow<int>(i))) {
146 for (
const auto& i : idam) {
147 if (
auto sector = decodeSectorImpl(narrow<int>(i));
149 (sector->sector == sectorNum) &&
150 (sector->dataIdx != -1)) {
159 for (
auto [i, d] :
enumerate(destination)) {
160 d =
read(idx +
int(i));
166 write(idx +
int(i), s);
173 unsigned end = start + size;
174 if (
end <= data.size()) {
177 unsigned part = unsigned(data.size()) - start;
243 for (
unsigned ii : idam) {
244 auto i = narrow<int>(ii);
245 if ((
read(i - 3) != 0xA1) ||
246 (
read(i - 2) != 0xA1) ||
247 (
read(i - 1) != 0xA1) ||
248 (
read(i - 0) != 0xFE))
continue;
251 if (
auto sector = decodeSectorImpl(i);
252 sector && (sector->dataIdx != -1)) {
253 int d = sector->dataIdx;
254 if ((
read(d - 4) != 0xA1) ||
255 (
read(d - 3) != 0xA1) ||
256 (
read(d - 2) != 0xA1))
continue;
264template<
typename Archive>
267 ar.serialize(
"idam", idam);
268 auto len = unsigned(data.size());
269 if (ar.versionAtLeast(version, 2)) {
270 ar.serialize(
"trackLength", len);
272 assert(Archive::IS_LOADER);
275 if constexpr (Archive::IS_LOADER) {
278 ar.serialize_blob(
"data", data);
282template<
typename Archive>
285 ar.serialize(
"addrIdx",
addrIdx,
This class calculates CRC numbers for the polygon x^16 + x^12 + x^5 + 1.
constexpr void update(uint8_t value)
Update CRC with one byte.
constexpr uint16_t getValue() const
Get current CRC value.
std::vector< Sector > decodeAll() const
Get info on all sectors in this track.
void write(int idx, uint8_t val, bool setIdam=false)
void addIdam(unsigned idx)
uint8_t read(int idx) const
void serialize(Archive &ar, unsigned version)
std::optional< Sector > decodeNextSector(unsigned startIdx) const
Get the next sector (starting from a certain index).
RawTrack(unsigned size=STANDARD_SIZE)
std::optional< Sector > decodeSector(uint8_t sectorNum) const
Get a sector with a specific number.
void applyWd2793ReadTrackQuirk()
int wrapIndex(int idx) const
void updateCrc(CRC16 &crc, int idx, int size) const
void writeBlock(int idx, std::span< const uint8_t > source)
void clear(unsigned size)
Clear track data.
void readBlock(int idx, std::span< uint8_t > destination) const
Like memcpy() but copy from/to circular buffer.
uint16_t calcCrc(int idx, int size) const
Convenience method to calculate CRC for part of this track.
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
This file implemented 3 utility functions:
auto lower_bound(ForwardRange &&range, const T &value, Compare comp={}, Proj proj={})
constexpr auto subspan(Range &&range, size_t offset, size_t count=std::dynamic_extent)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
void serialize(Archive &ar, unsigned version)
constexpr auto xrange(T e)
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)