mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-19 23:32:28 +00:00
Makes a first attempt at NIB support.
This commit is contained in:
parent
850a394eb5
commit
41075356e2
@ -78,7 +78,7 @@ void DiskII::set_data_register(uint8_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t DiskII::get_shift_register() {
|
uint8_t DiskII::get_shift_register() {
|
||||||
// printf("[%02x] ", shift_register_);
|
// if(shift_register_ & 0x80) printf("[%02x] ", shift_register_);
|
||||||
inputs_ &= ~input_command;
|
inputs_ &= ~input_command;
|
||||||
return shift_register_;
|
return shift_register_;
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,16 @@
|
|||||||
|
|
||||||
#include "NIB.hpp"
|
#include "NIB.hpp"
|
||||||
|
|
||||||
|
#include "../../Track/PCMTrack.hpp"
|
||||||
|
#include "../../Encodings/AppleGCR.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace Storage::Disk;
|
using namespace Storage::Disk;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const std::size_t track_length = 6656;
|
const long track_length = 6656;
|
||||||
const std::size_t number_of_tracks = 35;
|
const std::size_t number_of_tracks = 35;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -24,7 +29,7 @@ NIB::NIB(const std::string &file_name) :
|
|||||||
throw ErrorNotNIB;
|
throw ErrorNotNIB;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: all other validation.
|
// TODO: all other validation. I.e. does this look like a GCR disk?
|
||||||
}
|
}
|
||||||
|
|
||||||
int NIB::get_head_position_count() {
|
int NIB::get_head_position_count() {
|
||||||
@ -33,13 +38,59 @@ int NIB::get_head_position_count() {
|
|||||||
|
|
||||||
std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Disk::Track::Address address) {
|
std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||||
// NIBs contain data for even-numbered tracks underneath a single head only.
|
// NIBs contain data for even-numbered tracks underneath a single head only.
|
||||||
if(address.head || (address.position&1)) return nullptr;
|
if(address.head) return nullptr;
|
||||||
|
|
||||||
// const int file_track = address.position >> 1;
|
const long file_track = static_cast<long>(address.position >> 2);
|
||||||
// file_.seek(static_cast<long>(file_track * track_length), SEEK_SET);
|
file_.seek(file_track * track_length, SEEK_SET);
|
||||||
// std::vector<uint8_t> track_data = file_.read(track_length);
|
std::vector<uint8_t> track_data = file_.read(track_length);
|
||||||
|
|
||||||
// TODO: determine which FFs are syncs, and produce track.
|
// NIB files leave sync bytes implicit and make no guarantees
|
||||||
|
// about overall track positioning. So the approach taken here
|
||||||
|
// is to look for the epilogue sequence (which concludes all Apple
|
||||||
|
// tracks and headers), then treat all following FFs as a sync
|
||||||
|
// region, then switch back to ordinary behaviour as soon as a
|
||||||
|
// non-FF appears.
|
||||||
|
std::vector<Storage::Disk::PCMSegment> segments;
|
||||||
|
|
||||||
return nullptr;
|
std::size_t start_index = 0;
|
||||||
|
std::set<size_t> sync_starts;
|
||||||
|
|
||||||
|
// Establish where syncs start by finding instances of 0xd5 0xaa and then regressing
|
||||||
|
// from each along all preceding FFs.
|
||||||
|
for(size_t index = 0; index < track_data.size(); ++index) {
|
||||||
|
if(track_data[index] == 0xd5 && track_data[(index+1)%track_data.size()] == 0xaa) {
|
||||||
|
size_t start = index - 1;
|
||||||
|
while(track_data[start] == 0xff)
|
||||||
|
start = (start + track_data.size() - 1) % track_data.size();
|
||||||
|
|
||||||
|
sync_starts.insert((start + 1) % track_data.size());
|
||||||
|
if(start > index)
|
||||||
|
start_index = start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(start_index)
|
||||||
|
segments.push_back(Encodings::AppleGCR::six_and_two_sync(static_cast<int>(start_index)));
|
||||||
|
|
||||||
|
std::size_t index = start_index;
|
||||||
|
for(const auto &location: sync_starts) {
|
||||||
|
// Write from index to sync_start.
|
||||||
|
PCMSegment data_segment;
|
||||||
|
data_segment.data.insert(
|
||||||
|
data_segment.data.end(),
|
||||||
|
track_data.begin() + static_cast<off_t>(index),
|
||||||
|
track_data.begin() + static_cast<off_t>(location));
|
||||||
|
data_segment.number_of_bits = static_cast<unsigned int>(data_segment.data.size() * 8);
|
||||||
|
segments.push_back(std::move(data_segment));
|
||||||
|
|
||||||
|
// Add a sync from sync_start to end of 0xffs.
|
||||||
|
if(location == track_length-1) break;
|
||||||
|
|
||||||
|
index = location;
|
||||||
|
while(index < track_length && track_data[index] == 0xff)
|
||||||
|
++index;
|
||||||
|
segments.push_back(Encodings::AppleGCR::six_and_two_sync(static_cast<int>(index - location)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::shared_ptr<PCMTrack>(new PCMTrack(segments));
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ namespace Disk {
|
|||||||
Bits from each byte are taken MSB to LSB.
|
Bits from each byte are taken MSB to LSB.
|
||||||
*/
|
*/
|
||||||
struct PCMSegment {
|
struct PCMSegment {
|
||||||
Time length_of_a_bit;
|
Time length_of_a_bit = Time(1);
|
||||||
unsigned int number_of_bits = 0;
|
unsigned int number_of_bits = 0;
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user