mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-25 03:32:01 +00:00
Implements read-only MSA support.
This commit is contained in:
parent
8b397626bf
commit
345b32d6e3
@ -386,6 +386,8 @@
|
||||
<string>Owner</string>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<false/>
|
||||
<key>NSDocumentClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).MachineDocument</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
@ -406,6 +408,8 @@
|
||||
<string>Owner</string>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<false/>
|
||||
<key>NSDocumentClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).MachineDocument</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
|
@ -8,16 +8,77 @@
|
||||
|
||||
#include "MSA.hpp"
|
||||
|
||||
#include "Utility/ImplicitSectors.hpp"
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
MSA::MSA(const std::string &file_name) :
|
||||
file_(file_name) {
|
||||
const auto signature = file_.get16be();
|
||||
if(signature != 0x0e0f) throw Error::InvalidFormat;
|
||||
|
||||
sectors_per_track_ = file_.get16be();
|
||||
sides_ = 1 + file_.get16be();
|
||||
starting_track_ = file_.get16be();
|
||||
ending_track_ = file_.get16be();
|
||||
|
||||
// Create the uncompressed track list.
|
||||
while(true) {
|
||||
const auto data_length = file_.get16be();
|
||||
if(file_.eof()) break;
|
||||
|
||||
if(data_length == sectors_per_track_ * 512) {
|
||||
// This is an uncompressed track.
|
||||
uncompressed_tracks_.push_back(file_.read(data_length));
|
||||
} else {
|
||||
// This is an RLE-compressed track.
|
||||
std::vector<uint8_t> track;
|
||||
track.reserve(sectors_per_track_ * 512);
|
||||
uint16_t pointer = 0;
|
||||
while(pointer < data_length) {
|
||||
const auto byte = file_.get8();
|
||||
|
||||
// Compression scheme: if the byte E5 is encountered, an RLE run follows.
|
||||
// An RLE run is encoded as the byte to repeat plus a 16-bit repeat count.
|
||||
if(byte != 0xe5) {
|
||||
track.push_back(byte);
|
||||
++pointer;
|
||||
continue;
|
||||
}
|
||||
|
||||
pointer += 4;
|
||||
if(pointer > data_length) break;
|
||||
|
||||
const auto value = file_.get8();
|
||||
auto count = file_.get16be();
|
||||
while(count--) {
|
||||
track.push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
if(pointer != data_length || track.size() != sectors_per_track_ * 512) throw Error::InvalidFormat;
|
||||
uncompressed_tracks_.push_back(std::move(track));
|
||||
}
|
||||
}
|
||||
|
||||
if(uncompressed_tracks_.size() != (ending_track_ - starting_track_ + 1)*sides_) throw Error::InvalidFormat;
|
||||
}
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> MSA::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||
return nullptr;
|
||||
if(address.head >= sides_) return nullptr;
|
||||
|
||||
const auto position = address.position.as_int();
|
||||
if(position < starting_track_) return nullptr;
|
||||
if(position >= ending_track_) return nullptr;
|
||||
|
||||
const auto &track = uncompressed_tracks_[size_t(position) * size_t(sides_) + size_t(address.head)];
|
||||
return track_for_sectors(track.data(), sectors_per_track_, uint8_t(position), uint8_t(address.head), 0, 2, true);
|
||||
}
|
||||
|
||||
HeadPosition MSA::get_maximum_head_position() {
|
||||
return HeadPosition(10);
|
||||
return HeadPosition(ending_track_);
|
||||
}
|
||||
|
||||
int MSA::get_head_count() {
|
||||
return sides_;
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "../DiskImage.hpp"
|
||||
#include "../../../FileHolder.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
@ -25,10 +27,17 @@ class MSA final: public DiskImage {
|
||||
|
||||
// Implemented to satisfy @c DiskImage.
|
||||
HeadPosition get_maximum_head_position() override;
|
||||
int get_head_count() override;
|
||||
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) override;
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
uint16_t sectors_per_track_;
|
||||
uint16_t sides_;
|
||||
uint16_t starting_track_;
|
||||
uint16_t ending_track_;
|
||||
|
||||
std::vector<std::vector<uint8_t>> uncompressed_tracks_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
std::shared_ptr<Track> Storage::Disk::track_for_sectors(uint8_t *const source, int number_of_sectors, uint8_t track, uint8_t side, uint8_t first_sector, uint8_t size, bool is_double_density) {
|
||||
std::shared_ptr<Track> Storage::Disk::track_for_sectors(const uint8_t *const source, int number_of_sectors, uint8_t track, uint8_t side, uint8_t first_sector, uint8_t size, bool is_double_density) {
|
||||
std::vector<Storage::Encodings::MFM::Sector> sectors;
|
||||
|
||||
off_t byte_size = static_cast<off_t>(128 << size);
|
||||
|
@ -16,8 +16,8 @@
|
||||
namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
std::shared_ptr<Track> track_for_sectors(uint8_t *const source, int number_of_sectors, uint8_t track, uint8_t side, uint8_t first_sector, uint8_t size, bool is_double_density);
|
||||
void decode_sectors(Track &track, uint8_t *const destination, uint8_t first_sector, uint8_t last_sector, uint8_t sector_size, bool is_double_density);
|
||||
std::shared_ptr<Track> track_for_sectors(const uint8_t *source, int number_of_sectors, uint8_t track, uint8_t side, uint8_t first_sector, uint8_t size, bool is_double_density);
|
||||
void decode_sectors(Track &track, uint8_t *destination, uint8_t first_sector, uint8_t last_sector, uint8_t sector_size, bool is_double_density);
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user