2017-08-18 01:48:48 +00:00
|
|
|
//
|
|
|
|
// HFE.cpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 17/08/2017.
|
|
|
|
// Copyright © 2017 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "HFE.hpp"
|
|
|
|
|
2017-09-23 02:39:23 +00:00
|
|
|
#include "../../Track/PCMTrack.hpp"
|
2017-08-18 02:20:02 +00:00
|
|
|
|
2017-08-18 01:48:48 +00:00
|
|
|
using namespace Storage::Disk;
|
|
|
|
|
|
|
|
HFE::HFE(const char *file_name) :
|
|
|
|
Storage::FileHolder(file_name) {
|
2017-08-18 02:20:02 +00:00
|
|
|
if(!check_signature("HXCPICFE", 8)) throw ErrorNotHFE;
|
|
|
|
|
|
|
|
if(fgetc(file_)) throw ErrorNotHFE;
|
|
|
|
track_count_ = (unsigned int)fgetc(file_);
|
|
|
|
head_count_ = (unsigned int)fgetc(file_);
|
|
|
|
|
|
|
|
fseek(file_, 7, SEEK_CUR);
|
|
|
|
track_list_offset_ = (long)fgetc16le() << 9;
|
2017-08-18 01:48:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
HFE::~HFE() {
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int HFE::get_head_position_count() {
|
|
|
|
return track_count_;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int HFE::get_head_count() {
|
|
|
|
return head_count_;
|
|
|
|
}
|
|
|
|
|
2017-09-23 00:28:11 +00:00
|
|
|
std::shared_ptr<Track> HFE::get_track_at_position(unsigned int head, unsigned int position) {
|
2017-08-18 02:20:02 +00:00
|
|
|
// Get track position and length from the lookup table; data is then always interleaved
|
|
|
|
// based on an assumption of two heads.
|
|
|
|
fseek(file_, track_list_offset_ + position * 4, SEEK_SET);
|
|
|
|
|
|
|
|
long track_offset = (long)fgetc16le() << 9;
|
|
|
|
uint16_t track_length = fgetc16le();
|
|
|
|
|
|
|
|
fseek(file_, track_offset, SEEK_SET);
|
|
|
|
if(head) fseek(file_, 256, SEEK_CUR);
|
|
|
|
|
|
|
|
PCMSegment segment;
|
|
|
|
uint16_t side_length = track_length / 2;
|
|
|
|
segment.data.resize(side_length);
|
2017-08-18 02:28:00 +00:00
|
|
|
segment.number_of_bits = side_length * 8;
|
2017-08-18 02:20:02 +00:00
|
|
|
|
|
|
|
uint16_t c = 0;
|
|
|
|
while(c < side_length) {
|
|
|
|
uint16_t length = (uint16_t)std::min(256, side_length - c);
|
|
|
|
fread(&segment.data[c], 1, length, file_);
|
|
|
|
c += length;
|
|
|
|
fseek(file_, 256, SEEK_CUR);
|
|
|
|
}
|
|
|
|
|
2017-08-18 02:28:00 +00:00
|
|
|
// Flip bytes; HFE's preference is that the least-significant bit
|
|
|
|
// is serialised first, but PCMTrack posts the most-significant first.
|
|
|
|
for(size_t i = 0; i < segment.data.size(); i++) {
|
|
|
|
uint8_t original = segment.data[i];
|
|
|
|
uint8_t flipped_byte =
|
|
|
|
(uint8_t)(
|
|
|
|
((original & 0x01) << 7) |
|
|
|
|
((original & 0x02) << 5) |
|
|
|
|
((original & 0x04) << 3) |
|
|
|
|
((original & 0x08) << 1) |
|
|
|
|
((original & 0x10) >> 1) |
|
|
|
|
((original & 0x20) >> 3) |
|
|
|
|
((original & 0x40) >> 5) |
|
|
|
|
((original & 0x80) >> 7)
|
|
|
|
);
|
|
|
|
segment.data[i] = flipped_byte;
|
|
|
|
}
|
|
|
|
|
2017-08-18 02:20:02 +00:00
|
|
|
std::shared_ptr<Track> track(new PCMTrack(segment));
|
|
|
|
return track;
|
2017-08-18 01:48:48 +00:00
|
|
|
}
|
2017-09-23 00:28:11 +00:00
|
|
|
|