| 73 | |
| 74 | public: |
| 75 | std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) override |
| 76 | { |
| 77 | int strack = strackno(track, side); |
| 78 | if (strack >= ARRAY_SIZE(_header.track)) |
| 79 | return std::make_unique<Fluxmap>(); |
| 80 | uint32_t offset = Bytes(_header.track[strack], 4).reader().read_le32(); |
| 81 | if (offset == 0) |
| 82 | return std::make_unique<Fluxmap>(); |
| 83 | |
| 84 | ScpTrackHeader trackHeader; |
| 85 | _if.seekg(offset, std::ios::beg); |
| 86 | _if.read((char*)&trackHeader, sizeof(trackHeader)); |
| 87 | check_for_error(); |
| 88 | |
| 89 | if ((trackHeader.track_id[0] != 'T') || |
| 90 | (trackHeader.track_id[1] != 'R') || |
| 91 | (trackHeader.track_id[2] != 'K')) |
| 92 | error("corrupt SCP file"); |
| 93 | |
| 94 | std::vector<ScpTrackRevolution> revs(_header.revolutions); |
| 95 | for (int revolution = 0; revolution < _header.revolutions; revolution++) |
| 96 | { |
| 97 | ScpTrackRevolution trackrev; |
| 98 | _if.read((char*)&trackrev, sizeof(trackrev)); |
| 99 | check_for_error(); |
| 100 | revs[revolution] = trackrev; |
| 101 | } |
| 102 | |
| 103 | auto fluxmap = std::make_unique<Fluxmap>(); |
| 104 | nanoseconds_t pending = 0; |
| 105 | unsigned inputBytes = 0; |
| 106 | for (int revolution = 0; revolution < _header.revolutions; revolution++) |
| 107 | { |
| 108 | if (revolution != 0) |
| 109 | fluxmap->appendIndex(); |
| 110 | |
| 111 | uint32_t datalength = |
| 112 | Bytes(revs[revolution].length, 4).reader().read_le32(); |
| 113 | uint32_t dataoffset = |
| 114 | Bytes(revs[revolution].offset, 4).reader().read_le32(); |
| 115 | |
| 116 | Bytes data(datalength * 2); |
| 117 | _if.seekg(dataoffset + offset, std::ios::beg); |
| 118 | _if.read((char*)data.begin(), data.size()); |
| 119 | check_for_error(); |
| 120 | |
| 121 | ByteReader br(data); |
| 122 | for (int cell = 0; cell < datalength; cell++) |
| 123 | { |
| 124 | uint16_t interval = br.read_be16(); |
| 125 | if (interval) |
| 126 | { |
| 127 | fluxmap->appendInterval( |
| 128 | (interval + pending) * _resolution / NS_PER_TICK); |
| 129 | fluxmap->appendPulse(); |
| 130 | pending = 0; |
| 131 | } |
| 132 | else |