1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-04-11 14:37:37 +00:00

Introduces flush_tracks to Drive, while switching its interface to using Track::Address and adjusting associated integer types.

This commit is contained in:
Thomas Harte 2017-10-06 21:45:12 -04:00
parent f623bff5c3
commit 97a2be71e3
29 changed files with 150 additions and 238 deletions

View File

@ -239,7 +239,7 @@ uint8_t i8272::get_register(int address) {
active_head_ = (command_[1] >> 2)&1; \
status_[0] = (command_[1]&7); \
select_drive(active_drive_); \
get_drive().set_head((unsigned int)active_head_); \
get_drive().set_head(active_head_); \
set_is_double_density(command_[0] & 0x40);
#define WAIT_FOR_BYTES(n) \

View File

@ -53,7 +53,7 @@ void Microdisc::set_control_register(uint8_t control, uint8_t changes) {
// b4: side select
if(changes & 0x10) {
unsigned int head = (control & 0x10) ? 1 : 0;
int head = (control & 0x10) ? 1 : 0;
for(int c = 0; c < 4; c++) {
if(drives_[c]) drives_[c]->set_head(head);
}

View File

@ -69,7 +69,6 @@
4B4518851F75E91A00926311 /* DiskController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45187A1F75E91900926311 /* DiskController.cpp */; };
4B4518861F75E91A00926311 /* MFMDiskController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45187C1F75E91900926311 /* MFMDiskController.cpp */; };
4B4518871F75E91A00926311 /* DigitalPhaseLockedLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45187F1F75E91900926311 /* DigitalPhaseLockedLoop.cpp */; };
4B45189E1F75FD1C00926311 /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45188A1F75FD1B00926311 /* DiskImage.cpp */; };
4B45189F1F75FD1C00926311 /* AcornADF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45188D1F75FD1B00926311 /* AcornADF.cpp */; };
4B4518A01F75FD1C00926311 /* CPCDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45188F1F75FD1B00926311 /* CPCDSK.cpp */; };
4B4518A11F75FD1C00926311 /* D64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518911F75FD1B00926311 /* D64.cpp */; };
@ -77,7 +76,6 @@
4B4518A31F75FD1C00926311 /* HFE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518951F75FD1B00926311 /* HFE.cpp */; };
4B4518A41F75FD1C00926311 /* OricMFMDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */; };
4B4518A51F75FD1C00926311 /* SSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518991F75FD1B00926311 /* SSD.cpp */; };
4B4518A61F75FD1C00926311 /* SingleTrackDisk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45189C1F75FD1C00926311 /* SingleTrackDisk.cpp */; };
4B4A76301DB1A3FA007AAE2E /* AY38910.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */; };
4B4DC8211D2C2425003C5BF8 /* Vic20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */; };
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */; };
@ -603,7 +601,6 @@
4B45187F1F75E91900926311 /* DigitalPhaseLockedLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DigitalPhaseLockedLoop.cpp; sourceTree = "<group>"; };
4B4518801F75E91900926311 /* DigitalPhaseLockedLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DigitalPhaseLockedLoop.hpp; sourceTree = "<group>"; };
4B4518881F75ECB100926311 /* Track.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Track.hpp; sourceTree = "<group>"; };
4B45188A1F75FD1B00926311 /* DiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskImage.cpp; sourceTree = "<group>"; };
4B45188B1F75FD1B00926311 /* DiskImage.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DiskImage.hpp; sourceTree = "<group>"; };
4B45188D1F75FD1B00926311 /* AcornADF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AcornADF.cpp; sourceTree = "<group>"; };
4B45188E1F75FD1B00926311 /* AcornADF.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = AcornADF.hpp; sourceTree = "<group>"; };
@ -619,8 +616,6 @@
4B4518981F75FD1B00926311 /* OricMFMDSK.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OricMFMDSK.hpp; sourceTree = "<group>"; };
4B4518991F75FD1B00926311 /* SSD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SSD.cpp; sourceTree = "<group>"; };
4B45189A1F75FD1B00926311 /* SSD.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SSD.hpp; sourceTree = "<group>"; };
4B45189C1F75FD1C00926311 /* SingleTrackDisk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SingleTrackDisk.cpp; sourceTree = "<group>"; };
4B45189D1F75FD1C00926311 /* SingleTrackDisk.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SingleTrackDisk.hpp; sourceTree = "<group>"; };
4B4518A71F76004200926311 /* TapeParser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = TapeParser.hpp; path = Parsers/TapeParser.hpp; sourceTree = "<group>"; };
4B4518A81F76022000926311 /* DiskImageImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DiskImageImplementation.hpp; sourceTree = "<group>"; };
4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AY38910.cpp; path = AY38910/AY38910.cpp; sourceTree = "<group>"; };
@ -1472,7 +1467,6 @@
4B4518891F75FD1B00926311 /* DiskImage */ = {
isa = PBXGroup;
children = (
4B45188A1F75FD1B00926311 /* DiskImage.cpp */,
4B45188B1F75FD1B00926311 /* DiskImage.hpp */,
4B4518A81F76022000926311 /* DiskImageImplementation.hpp */,
4B45188C1F75FD1B00926311 /* Formats */,
@ -1504,15 +1498,6 @@
path = Formats;
sourceTree = "<group>";
};
4B45189B1F75FD1C00926311 /* SingleTrackDisk */ = {
isa = PBXGroup;
children = (
4B45189C1F75FD1C00926311 /* SingleTrackDisk.cpp */,
4B45189D1F75FD1C00926311 /* SingleTrackDisk.hpp */,
);
path = SingleTrackDisk;
sourceTree = "<group>";
};
4B4A762D1DB1A35C007AAE2E /* AY38910 */ = {
isa = PBXGroup;
children = (
@ -1779,7 +1764,6 @@
4B45187E1F75E91900926311 /* DPLL */,
4BB697CF1D4BA44900248BDF /* Encodings */,
4B3FE75F1F3CF6BA00448EE4 /* Parsers */,
4B45189B1F75FD1C00926311 /* SingleTrackDisk */,
4B4518701F75E91800926311 /* Track */,
);
path = Disk;
@ -2923,7 +2907,6 @@
4B8378DC1F336631005CA9E4 /* CharacterMapper.cpp in Sources */,
4B8378E51F3378C4005CA9E4 /* CharacterMapper.cpp in Sources */,
4B322E041F5A2E3C004EB04C /* Z80Base.cpp in Sources */,
4B45189E1F75FD1C00926311 /* DiskImage.cpp in Sources */,
4B4518A31F75FD1C00926311 /* HFE.cpp in Sources */,
4B8378E21F336920005CA9E4 /* CharacterMapper.cpp in Sources */,
4B4518A11F75FD1C00926311 /* D64.cpp in Sources */,
@ -2996,7 +2979,6 @@
4B8FE2291DA1EDDF0090D3CE /* ElectronOptionsPanel.swift in Sources */,
4B55CE5D1C3B7D6F0093A61B /* CSOpenGLView.m in Sources */,
4BB697CB1D4B6D3E00248BDF /* TimedEventLoop.cpp in Sources */,
4B4518A61F75FD1C00926311 /* SingleTrackDisk.cpp in Sources */,
4BBC951E1F368D83008F4C34 /* i8272.cpp in Sources */,
4BF1354C1D6D2C300054B2EA /* StaticAnalyser.cpp in Sources */,
4B4A76301DB1A3FA007AAE2E /* AY38910.cpp in Sources */,

View File

@ -31,25 +31,28 @@ class Disk {
This is not necessarily a track count. There is no implicit guarantee that every position will
return a distinct track, or e.g. if the media is holeless will return any track at all.
*/
virtual unsigned int get_head_position_count() = 0;
virtual int get_head_position_count() = 0;
/*!
@returns the number of heads (and, therefore, impliedly surfaces) available on this disk.
*/
virtual unsigned int get_head_count() = 0;
virtual int get_head_count() = 0;
/*!
@returns the @c Track at @c position underneath @c head if there are any detectable events there;
returns @c nullptr otherwise.
*/
virtual std::shared_ptr<Track> get_track_at_position(unsigned int head, unsigned int position) = 0;
virtual std::shared_ptr<Track> get_track_at_position(Track::Address address) = 0;
/*!
Replaces the Track at position @c position underneath @c head with @c track. Ignored if this disk is read-only.
Subclasses that are not read-only should use the protected methods @c get_is_modified and, optionally,
@c get_modified_track_at_position to query for changes when closing.
*/
virtual void set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track) = 0;
virtual void set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track) = 0;
/*!
Provides a hint that no further tracks are likely to be written for a while.
*/
virtual void flush_tracks() = 0;
/*!
@returns whether the disk image is read only. Defaults to @c true if not overridden.

View File

@ -1,15 +0,0 @@
//
// DiskImage.cpp
// Clock Signal
//
// Created by Thomas Harte on 21/09/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "DiskImage.hpp"
using namespace Storage::Disk;
int DiskImageHolderBase::get_id_for_track_at_position(unsigned int head, unsigned int position) {
return (int)(position * get_head_count() + head);
}

View File

@ -35,25 +35,28 @@ class DiskImage {
This is not necessarily a track count. There is no implicit guarantee that every position will
return a distinct track, or e.g. if the media is holeless will return any track at all.
*/
virtual unsigned int get_head_position_count() = 0;
virtual int get_head_position_count() = 0;
/*!
@returns the number of heads (and, therefore, impliedly surfaces) available on this disk.
*/
virtual unsigned int get_head_count() { return 1; }
virtual int get_head_count() { return 1; }
/*!
@returns the @c Track at @c position underneath @c head if there are any detectable events there;
returns @c nullptr otherwise.
*/
virtual std::shared_ptr<Track> get_track_at_position(unsigned int head, unsigned int position) = 0;
virtual std::shared_ptr<Track> get_track_at_position(Track::Address address) = 0;
/*!
Replaces the Track at position @c position underneath @c head with @c track. Ignored if this disk is read-only.
Subclasses that are not read-only should use the protected methods @c get_is_modified and, optionally,
@c get_modified_track_at_position to query for changes when closing.
*/
virtual void set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track) {}
virtual void set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track) {}
/*!
Communicates that it is likely to be a while before any more tracks are written.
*/
virtual void flush_tracks() {}
/*!
@returns whether the disk image is read only. Defaults to @c true if not overridden.
@ -63,8 +66,7 @@ class DiskImage {
class DiskImageHolderBase: public Disk {
protected:
int get_id_for_track_at_position(unsigned int head, unsigned int position);
std::map<int, std::shared_ptr<Track>> cached_tracks_;
std::map<Track::Address, std::shared_ptr<Track>> cached_tracks_;
std::unique_ptr<Concurrency::AsyncTaskQueue> update_queue_;
};
@ -79,10 +81,11 @@ template <typename T> class DiskImageHolder: public DiskImageHolderBase {
disk_image_(args...) {}
~DiskImageHolder();
unsigned int get_head_position_count();
unsigned int get_head_count();
std::shared_ptr<Track> get_track_at_position(unsigned int head, unsigned int position);
void set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track);
int get_head_position_count();
int get_head_count();
std::shared_ptr<Track> get_track_at_position(Track::Address address);
void set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track);
void flush_tracks();
bool get_is_read_only();
private:

View File

@ -6,11 +6,11 @@
// Copyright © 2017 Thomas Harte. All rights reserved.
//
template <typename T> unsigned int DiskImageHolder<T>::get_head_position_count() {
template <typename T> int DiskImageHolder<T>::get_head_position_count() {
return disk_image_.get_head_position_count();
}
template <typename T> unsigned int DiskImageHolder<T>::get_head_count() {
template <typename T> int DiskImageHolder<T>::get_head_count() {
return disk_image_.get_head_count();
}
@ -18,28 +18,29 @@ template <typename T> bool DiskImageHolder<T>::get_is_read_only() {
return disk_image_.get_is_read_only();
}
template <typename T> void DiskImageHolder<T>::set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track) {
template <typename T> void DiskImageHolder<T>::flush_tracks() {
}
template <typename T> void DiskImageHolder<T>::set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track) {
if(disk_image_.get_is_read_only()) return;
int address = get_id_for_track_at_position(head, position);
cached_tracks_[address] = track;
if(!update_queue_) update_queue_.reset(new Concurrency::AsyncTaskQueue);
std::shared_ptr<Track> track_copy(track->clone());
update_queue_->enqueue([this, head, position, track_copy] {
disk_image_.set_track_at_position(head, position, track_copy);
update_queue_->enqueue([this, address, track_copy] {
disk_image_.set_track_at_position(address, track_copy);
});
}
template <typename T> std::shared_ptr<Track> DiskImageHolder<T>::get_track_at_position(unsigned int head, unsigned int position) {
if(head >= get_head_count()) return nullptr;
if(position >= get_head_position_count()) return nullptr;
template <typename T> std::shared_ptr<Track> DiskImageHolder<T>::get_track_at_position(Track::Address address) {
if(address.head >= get_head_count()) return nullptr;
if(address.position >= get_head_position_count()) return nullptr;
int address = get_id_for_track_at_position(head, position);
std::map<int, std::shared_ptr<Track>>::iterator cached_track = cached_tracks_.find(address);
auto cached_track = cached_tracks_.find(address);
if(cached_track != cached_tracks_.end()) return cached_track->second;
std::shared_ptr<Track> track = disk_image_.get_track_at_position(head, position);
std::shared_ptr<Track> track = disk_image_.get_track_at_position(address);
if(!track) return nullptr;
cached_tracks_[address] = track;
return track;

View File

@ -11,8 +11,8 @@
#include "Utility/ImplicitSectors.hpp"
namespace {
static const unsigned int sectors_per_track = 16;
static const unsigned int sector_size = 1;
static const int sectors_per_track = 16;
static const int sector_size = 1;
}
using namespace Storage::Disk;
@ -36,14 +36,14 @@ AcornADF::AcornADF(const char *file_name) : MFMSectorDump(file_name) {
set_geometry(sectors_per_track, sector_size, true);
}
unsigned int AcornADF::get_head_position_count() {
int AcornADF::get_head_position_count() {
return 80;
}
unsigned int AcornADF::get_head_count() {
int AcornADF::get_head_count() {
return 1;
}
long AcornADF::get_file_offset_for_position(unsigned int head, unsigned int position) {
return (position * 1 + head) * (128 << sector_size) * sectors_per_track;
long AcornADF::get_file_offset_for_position(Track::Address address) {
return (address.position * 1 + address.head) * (128 << sector_size) * sectors_per_track;
}

View File

@ -31,11 +31,11 @@ class AcornADF: public MFMSectorDump {
ErrorNotAcornADF,
};
unsigned int get_head_position_count();
unsigned int get_head_count();
int get_head_position_count();
int get_head_count();
private:
long get_file_offset_for_position(unsigned int head, unsigned int position);
long get_file_offset_for_position(Track::Address address);
};
}

View File

@ -23,13 +23,13 @@ CPCDSK::CPCDSK(const char *file_name) :
// Don't really care about about the creator; skip.
fseek(file_, 0x30, SEEK_SET);
head_position_count_ = (unsigned int)fgetc(file_);
head_count_ = (unsigned int)fgetc(file_);
head_position_count_ = fgetc(file_);
head_count_ = fgetc(file_);
if(is_extended_) {
// Skip two unused bytes and grab the track size table.
fseek(file_, 2, SEEK_CUR);
for(unsigned int c = 0; c < head_position_count_ * head_count_; c++) {
for(int c = 0; c < head_position_count_ * head_count_; c++) {
track_sizes_.push_back((size_t)(fgetc(file_) << 8));
}
} else {
@ -37,17 +37,17 @@ CPCDSK::CPCDSK(const char *file_name) :
}
}
unsigned int CPCDSK::get_head_position_count() {
int CPCDSK::get_head_position_count() {
return head_position_count_;
}
unsigned int CPCDSK::get_head_count() {
int CPCDSK::get_head_count() {
return head_count_;
}
std::shared_ptr<Track> CPCDSK::get_track_at_position(unsigned int head, unsigned int position) {
std::shared_ptr<Track> CPCDSK::get_track_at_position(Track::Address address) {
// Given that thesea are interleaved images, determine which track, chronologically, is being requested.
unsigned int chronological_track = (position * head_count_) + head;
size_t chronological_track = static_cast<size_t>((address.position * head_count_) + address.head);
// All DSK images reserve 0x100 bytes for their headers.
long file_offset = 0x100;
@ -60,14 +60,14 @@ std::shared_ptr<Track> CPCDSK::get_track_at_position(unsigned int head, unsigned
}
// Sum the lengths of all tracks prior to the interesting one to get a file offset.
unsigned int t = 0;
size_t t = 0;
while(t < chronological_track && t < track_sizes_.size()) {
file_offset += track_sizes_[t];
t++;
}
} else {
// Tracks are a fixed size in the original DSK file format.
file_offset += size_of_a_track_ * chronological_track;
file_offset += size_of_a_track_ * static_cast<long>(chronological_track);
}
// Find the track, and skip the unused part of track information.

View File

@ -35,15 +35,14 @@ class CPCDSK: public DiskImage, public Storage::FileHolder {
};
// implemented to satisfy @c Disk
unsigned int get_head_position_count();
unsigned int get_head_count();
int get_head_position_count();
int get_head_count();
using DiskImage::get_is_read_only;
std::shared_ptr<Track> get_track_at_position(unsigned int head, unsigned int position);
std::shared_ptr<Track> get_track_at_position(Track::Address address);
private:
unsigned int head_count_;
unsigned int head_position_count_;
int head_count_;
int head_position_count_;
bool is_extended_;
// Used only for non-extended disks.

View File

@ -35,18 +35,18 @@ D64::D64(const char *file_name) :
}
}
unsigned int D64::get_head_position_count() {
int D64::get_head_position_count() {
return number_of_tracks_*2;
}
std::shared_ptr<Track> D64::get_track_at_position(unsigned int head, unsigned int position) {
std::shared_ptr<Track> D64::get_track_at_position(Track::Address address) {
// every other track is missing, as is any head above 0
if(position&1 || head)
if(address.position&1 || address.head)
return std::shared_ptr<Track>();
// figure out where this track starts on the disk
int offset_to_track = 0;
int tracks_to_traverse = position >> 1;
int tracks_to_traverse = address.position >> 1;
int zone_sizes[] = {17, 7, 6, 10};
int sectors_by_zone[] = {21, 19, 18, 17};
@ -96,7 +96,7 @@ std::shared_ptr<Track> D64::get_track_at_position(unsigned int head, unsigned in
sector_data[0] = sector_data[1] = sector_data[2] = 0xff;
uint8_t sector_number = (uint8_t)(sector); // sectors count from 0
uint8_t track_number = (uint8_t)((position >> 1) + 1); // tracks count from 1
uint8_t track_number = (uint8_t)((address.position >> 1) + 1); // tracks count from 1
uint8_t checksum = (uint8_t)(sector_number ^ track_number ^ disk_id_ ^ (disk_id_ >> 8));
uint8_t header_start[4] = {
0x08, checksum, sector_number, track_number

View File

@ -33,12 +33,12 @@ class D64: public DiskImage, public Storage::FileHolder {
};
// implemented to satisfy @c Disk
unsigned int get_head_position_count();
int get_head_position_count();
using DiskImage::get_is_read_only;
std::shared_ptr<Track> get_track_at_position(unsigned int head, unsigned int position);
std::shared_ptr<Track> get_track_at_position(Track::Address address);
private:
unsigned int number_of_tracks_;
int number_of_tracks_;
uint16_t disk_id_;
};

View File

@ -28,22 +28,22 @@ G64::G64(const char *file_name) :
maximum_track_size_ = fgetc16le();
}
unsigned int G64::get_head_position_count() {
int G64::get_head_position_count() {
// give at least 84 tracks, to yield the normal geometry but,
// if there are more, shove them in
return number_of_tracks_ > 84 ? number_of_tracks_ : 84;
}
std::shared_ptr<Track> G64::get_track_at_position(unsigned int head, unsigned int position) {
std::shared_ptr<Track> G64::get_track_at_position(Track::Address address) {
std::shared_ptr<Track> resulting_track;
// if there's definitely no track here, return the empty track
// (TODO: should be supplying one with an index hole?)
if(position >= number_of_tracks_) return resulting_track;
if(head >= 1) return resulting_track;
if(address.position >= number_of_tracks_) return resulting_track;
if(address.head >= 1) return resulting_track;
// seek to this track's entry in the track table
fseek(file_, (long)((position * 4) + 0xc), SEEK_SET);
fseek(file_, (long)((address.position * 4) + 0xc), SEEK_SET);
// read the track offset
uint32_t track_offset;
@ -64,7 +64,7 @@ std::shared_ptr<Track> G64::get_track_at_position(unsigned int head, unsigned in
fread(&track_contents[0], 1, track_length, file_);
// seek to this track's entry in the speed zone table
fseek(file_, (long)((position * 4) + 0x15c), SEEK_SET);
fseek(file_, (long)((address.position * 4) + 0x15c), SEEK_SET);
// read the speed zone offsrt
uint32_t speed_zone_offset;

View File

@ -36,8 +36,8 @@ class G64: public DiskImage, public Storage::FileHolder {
};
// implemented to satisfy @c Disk
unsigned int get_head_position_count();
std::shared_ptr<Track> get_track_at_position(unsigned int head, unsigned int position);
int get_head_position_count();
std::shared_ptr<Track> get_track_at_position(Track::Address address);
using DiskImage::get_is_read_only;
private:

View File

@ -19,8 +19,8 @@ HFE::HFE(const char *file_name) :
if(!check_signature("HXCPICFE", 8)) throw ErrorNotHFE;
if(fgetc(file_)) throw ErrorNotHFE;
track_count_ = (unsigned int)fgetc(file_);
head_count_ = (unsigned int)fgetc(file_);
track_count_ = fgetc(file_);
head_count_ = fgetc(file_);
fseek(file_, 7, SEEK_CUR);
track_list_offset_ = (long)fgetc16le() << 9;
@ -29,11 +29,11 @@ HFE::HFE(const char *file_name) :
HFE::~HFE() {
}
unsigned int HFE::get_head_position_count() {
int HFE::get_head_position_count() {
return track_count_;
}
unsigned int HFE::get_head_count() {
int HFE::get_head_count() {
return head_count_;
}
@ -44,25 +44,25 @@ unsigned int HFE::get_head_count() {
To read the track, start from the current file position, read 256 bytes,
skip 256 bytes, read 256 bytes, skip 256 bytes, etc.
*/
uint16_t HFE::seek_track(unsigned int head, unsigned int position) {
uint16_t HFE::seek_track(Track::Address address) {
// 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);
fseek(file_, track_list_offset_ + address.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);
if(address.head) fseek(file_, 256, SEEK_CUR);
return track_length / 2;
}
std::shared_ptr<Track> HFE::get_track_at_position(unsigned int head, unsigned int position) {
std::shared_ptr<Track> HFE::get_track_at_position(Track::Address address) {
PCMSegment segment;
{
std::lock_guard<std::mutex> lock_guard(file_access_mutex_);
uint16_t track_length = seek_track(head, position);
uint16_t track_length = seek_track(address);
segment.data.resize(track_length);
segment.number_of_bits = track_length * 8;
@ -84,9 +84,9 @@ std::shared_ptr<Track> HFE::get_track_at_position(unsigned int head, unsigned in
return track;
}
void HFE::set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track) {
void HFE::set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track) {
std::unique_lock<std::mutex> lock_guard(file_access_mutex_);
uint16_t track_length = seek_track(head, position);
uint16_t track_length = seek_track(address);
lock_guard.unlock();
PCMSegment segment = Storage::Disk::track_serialisation(*track, Storage::Time(1, track_length * 8));
@ -94,7 +94,7 @@ void HFE::set_track_at_position(unsigned int head, unsigned int position, const
uint16_t data_length = std::min(static_cast<uint16_t>(segment.data.size()), track_length);
lock_guard.lock();
seek_track(head, position);
seek_track(address);
uint16_t c = 0;
while(c < data_length) {

View File

@ -34,17 +34,17 @@ class HFE: public DiskImage, public Storage::FileHolder {
};
// implemented to satisfy @c Disk
unsigned int get_head_position_count();
unsigned int get_head_count();
int get_head_position_count();
int get_head_count();
using Storage::FileHolder::get_is_read_only;
void set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track);
std::shared_ptr<Track> get_track_at_position(unsigned int head, unsigned int position);
void set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track);
std::shared_ptr<Track> get_track_at_position(Track::Address address);
private:
uint16_t seek_track(unsigned int head, unsigned int position);
uint16_t seek_track(Track::Address address);
unsigned int head_count_;
unsigned int track_count_;
int head_count_;
int track_count_;
long track_list_offset_;
};

View File

@ -20,11 +20,11 @@ void MFMSectorDump::set_geometry(int sectors_per_track, uint8_t sector_size, boo
is_double_density_ = is_double_density;
}
std::shared_ptr<Track> MFMSectorDump::get_track_at_position(unsigned int head, unsigned int position) {
std::shared_ptr<Track> MFMSectorDump::get_track_at_position(Track::Address address) {
uint8_t sectors[(128 << sector_size_)*sectors_per_track_];
if(head > 1) return nullptr;
long file_offset = get_file_offset_for_position(head, position);
if(address.head > 1) return nullptr;
long file_offset = get_file_offset_for_position(address);
{
std::lock_guard<std::mutex> lock_guard(file_access_mutex_);
@ -32,15 +32,15 @@ std::shared_ptr<Track> MFMSectorDump::get_track_at_position(unsigned int head, u
fread(sectors, 1, sizeof(sectors), file_);
}
return track_for_sectors(sectors, static_cast<uint8_t>(position), static_cast<uint8_t>(head), 0, sector_size_, is_double_density_);
return track_for_sectors(sectors, static_cast<uint8_t>(address.position), static_cast<uint8_t>(address.head), 0, sector_size_, is_double_density_);
}
void MFMSectorDump::set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track) {
void MFMSectorDump::set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track) {
uint8_t parsed_track[(128 << sector_size_)*sectors_per_track_];
// Assumption here: sector IDs will run from 0.
decode_sectors(*track, parsed_track, 0, static_cast<uint8_t>(sectors_per_track_-1), sector_size_, is_double_density_);
long file_offset = get_file_offset_for_position(head, position);
long file_offset = get_file_offset_for_position(address);
std::lock_guard<std::mutex> lock_guard(file_access_mutex_);
ensure_file_is_at_least_length(file_offset);

View File

@ -24,12 +24,12 @@ class MFMSectorDump: public DiskImage, public Storage::FileHolder {
void set_geometry(int sectors_per_track, uint8_t sector_size, bool is_double_density);
using Storage::FileHolder::get_is_read_only;
void set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track);
std::shared_ptr<Track> get_track_at_position(unsigned int head, unsigned int position);
void set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track);
std::shared_ptr<Track> get_track_at_position(Track::Address address);
private:
std::mutex file_access_mutex_;
virtual long get_file_offset_for_position(unsigned int head, unsigned int position) = 0;
virtual long get_file_offset_for_position(Track::Address address) = 0;
int sectors_per_track_ = 0;
uint8_t sector_size_ = 0;

View File

@ -29,32 +29,32 @@ OricMFMDSK::OricMFMDSK(const char *file_name) :
throw ErrorNotOricMFMDSK;
}
unsigned int OricMFMDSK::get_head_position_count() {
return track_count_;
int OricMFMDSK::get_head_position_count() {
return static_cast<int>(track_count_);
}
unsigned int OricMFMDSK::get_head_count() {
return head_count_;
int OricMFMDSK::get_head_count() {
return static_cast<int>(head_count_);
}
long OricMFMDSK::get_file_offset_for_position(unsigned int head, unsigned int position) {
long seek_offset = 0;
long OricMFMDSK::get_file_offset_for_position(Track::Address address) {
int seek_offset = 0;
switch(geometry_type_) {
case 1:
seek_offset = (head * track_count_) + position;
seek_offset = address.head * static_cast<int>(track_count_) + address.position;
break;
case 2:
seek_offset = (position * track_count_ * head_count_) + head;
seek_offset = address.position * static_cast<int>(track_count_ * head_count_) + address.head;
break;
}
return (seek_offset * 6400) + 256;
return static_cast<long>(seek_offset) * 6400 + 256;
}
std::shared_ptr<Track> OricMFMDSK::get_track_at_position(unsigned int head, unsigned int position) {
std::shared_ptr<Track> OricMFMDSK::get_track_at_position(Track::Address address) {
PCMSegment segment;
{
std::lock_guard<std::mutex> lock_guard(file_access_mutex_);
fseek(file_, get_file_offset_for_position(head, position), SEEK_SET);
fseek(file_, get_file_offset_for_position(address), SEEK_SET);
// The file format omits clock bits. So it's not a genuine MFM capture.
// A consumer must contextually guess when an FB, FC, etc is meant to be a control mark.
@ -114,7 +114,7 @@ std::shared_ptr<Track> OricMFMDSK::get_track_at_position(unsigned int head, unsi
return track;
}
void OricMFMDSK::set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track) {
void OricMFMDSK::set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track) {
PCMSegment segment = Storage::Disk::track_serialisation(*track, Storage::Encodings::MFM::MFMBitLength);
Storage::Encodings::MFM::Shifter shifter;
shifter.set_is_double_density(true);
@ -153,7 +153,7 @@ void OricMFMDSK::set_track_at_position(unsigned int head, unsigned int position,
}
}
long file_offset = get_file_offset_for_position(head, position);
long file_offset = get_file_offset_for_position(address);
std::lock_guard<std::mutex> lock_guard(file_access_mutex_);
fseek(file_, file_offset, SEEK_SET);

View File

@ -32,15 +32,15 @@ class OricMFMDSK: public DiskImage, public Storage::FileHolder {
};
// implemented to satisfy @c Disk
unsigned int get_head_position_count();
unsigned int get_head_count();
int get_head_position_count();
int get_head_count();
using Storage::FileHolder::get_is_read_only;
void set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track);
std::shared_ptr<Track> get_track_at_position(unsigned int head, unsigned int position);
void set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track);
std::shared_ptr<Track> get_track_at_position(Track::Address address);
private:
std::mutex file_access_mutex_;
long get_file_offset_for_position(unsigned int head, unsigned int position);
long get_file_offset_for_position(Track::Address address);
uint32_t head_count_;
uint32_t track_count_;

View File

@ -11,8 +11,8 @@
#include "Utility/ImplicitSectors.hpp"
namespace {
static const unsigned int sectors_per_track = 10;
static const unsigned int sector_size = 1;
static const int sectors_per_track = 10;
static const int sector_size = 1;
}
using namespace Storage::Disk;
@ -27,21 +27,21 @@ SSD::SSD(const char *file_name) : MFMSectorDump(file_name) {
// this has two heads if the suffix is .dsd, one if it's .ssd
head_count_ = (tolower(file_name[strlen(file_name) - 3]) == 'd') ? 2 : 1;
track_count_ = (unsigned int)(file_stats_.st_size / (256 * 10));
track_count_ = static_cast<int>(file_stats_.st_size / (256 * 10));
if(track_count_ < 40) track_count_ = 40;
else if(track_count_ < 80) track_count_ = 80;
set_geometry(sectors_per_track, sector_size, false);
}
unsigned int SSD::get_head_position_count() {
int SSD::get_head_position_count() {
return track_count_;
}
unsigned int SSD::get_head_count() {
int SSD::get_head_count() {
return head_count_;
}
long SSD::get_file_offset_for_position(unsigned int head, unsigned int position) {
return (position * head_count_ + head) * 256 * 10;
long SSD::get_file_offset_for_position(Track::Address address) {
return (address.position * head_count_ + address.head) * 256 * 10;
}

View File

@ -31,14 +31,14 @@ class SSD: public MFMSectorDump {
ErrorNotSSD,
};
unsigned int get_head_position_count();
unsigned int get_head_count();
int get_head_position_count();
int get_head_count();
private:
long get_file_offset_for_position(unsigned int head, unsigned int position);
long get_file_offset_for_position(Track::Address address);
unsigned int head_count_;
unsigned int track_count_;
int head_count_;
int track_count_;
};
}

View File

@ -15,7 +15,7 @@
using namespace Storage::Disk;
Drive::Drive(unsigned int input_clock_rate, int revolutions_per_minute, unsigned int number_of_heads):
Drive::Drive(unsigned int input_clock_rate, int revolutions_per_minute, int number_of_heads):
Storage::TimedEventLoop(input_clock_rate),
rotational_multiplier_(60, revolutions_per_minute),
available_heads_(number_of_heads) {
@ -51,7 +51,7 @@ void Drive::step(int direction) {
}
}
void Drive::set_head(unsigned int head) {
void Drive::set_head(int head) {
head = std::min(head, available_heads_ - 1);
if(head != head_) {
head_ = head;
@ -83,6 +83,7 @@ void Drive::set_motor_on(bool motor_is_on) {
motor_is_on_ = motor_is_on;
if(!motor_is_on) {
ready_index_count_ = 0;
if(disk_) disk_->flush_tracks();
}
update_sleep_observer();
}
@ -178,12 +179,12 @@ void Drive::process_next_event() {
#pragma mark - Track management
std::shared_ptr<Track> Drive::get_track() {
if(disk_) return disk_->get_track_at_position(head_, (unsigned int)head_position_);
if(disk_) return disk_->get_track_at_position(Track::Address(head_, head_position_));
return nullptr;
}
void Drive::set_track(const std::shared_ptr<Track> &track) {
if(disk_) disk_->set_track_at_position(head_, (unsigned int)head_position_, track);
if(disk_) disk_->set_track_at_position(Track::Address(head_, head_position_), track);
}
void Drive::setup_track() {

View File

@ -23,7 +23,7 @@ namespace Disk {
class Drive: public Sleeper, public TimedEventLoop {
public:
Drive(unsigned int input_clock_rate, int revolutions_per_minute, unsigned int number_of_heads);
Drive(unsigned int input_clock_rate, int revolutions_per_minute, int number_of_heads);
/*!
Replaces whatever is in the drive with @c disk.
@ -49,7 +49,7 @@ class Drive: public Sleeper, public TimedEventLoop {
/*!
Sets the current read head.
*/
void set_head(unsigned int head);
void set_head(int head);
/*!
@returns @c true if the inserted disk is read-only or no disk is inserted; @c false otherwise.
@ -139,8 +139,8 @@ class Drive: public Sleeper, public TimedEventLoop {
// A record of head position and active head.
int head_position_ = 0;
unsigned int head_ = 0;
unsigned int available_heads_ = 0;
int head_ = 0;
int available_heads_ = 0;
// Motor control state.
bool motor_is_on_ = false;

View File

@ -22,7 +22,7 @@ void Parser::install_sectors_from_track(const Storage::Disk::Track::Address &add
return;
}
std::shared_ptr<Storage::Disk::Track> track = disk_->get_track_at_position((unsigned int)address.head, (unsigned int)address.position);
std::shared_ptr<Storage::Disk::Track> track = disk_->get_track_at_position(address);
if(!track) {
return;
}
@ -39,9 +39,7 @@ void Parser::install_sectors_from_track(const Storage::Disk::Track::Address &add
}
Sector *Parser::get_sector(int head, int track, uint8_t sector) {
Disk::Track::Address address;
address.position = track;
address.head = head;
Disk::Track::Address address(head, track);
install_sectors_from_track(address);
auto sectors = sectors_by_address_by_track_.find(address);

View File

@ -1,22 +0,0 @@
//
// SingleTrackDisk.cpp
// Clock Signal
//
// Created by Thomas Harte on 10/09/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "SingleTrackDisk.hpp"
using namespace Storage::Disk;
SingleTrackDiskImage::SingleTrackDiskImage(const std::shared_ptr<Track> &track) :
track_(track) {}
unsigned int SingleTrackDiskImage::get_head_position_count() {
return 1;
}
std::shared_ptr<Track> SingleTrackDiskImage::get_track_at_position(unsigned int head, unsigned int position) {
return track_;
}

View File

@ -1,34 +0,0 @@
//
// SingleTrackDisk.hpp
// Clock Signal
//
// Created by Thomas Harte on 10/09/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef SingleTrackDisk_hpp
#define SingleTrackDisk_hpp
#include "DiskImage.hpp"
namespace Storage {
namespace Disk {
/*!
Provides a disk that has houses a single track.
*/
class SingleTrackDiskImage: public DiskImage {
public:
/// Constructs a single-track disk with the track @c track.
SingleTrackDiskImage(const std::shared_ptr<Track> &track);
unsigned int get_head_position_count();
std::shared_ptr<Track> get_track_at_position(unsigned int head, unsigned int position);
private:
std::shared_ptr<Track> track_;
};
}
}
#endif /* SingleTrackDisk_hpp */

View File

@ -10,6 +10,7 @@
#define Track_h
#include "../../Storage.hpp"
#include <tuple>
namespace Storage {
namespace Disk {
@ -29,14 +30,9 @@ class Track {
int head, position;
bool operator < (const Address &rhs) const {
return (head < rhs.head) || (position < rhs.position);
return std::tie(head, position) < std::tie(rhs.head, rhs.position);
}
// Address(const Address &rhs) noexcept : head(rhs.head), position(rhs.position) {}
// const Address &operator =(const Address &rhs) {
// head = rhs.head;
// position = rhs.position;
// return *this;
// }
Address(int head, int position) : head(head), position(position) {}
};
/*!