mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-11 14:37:37 +00:00
Factors out the more egregious similarities between ADF and SSD.
This commit is contained in:
parent
19eb975c73
commit
5dd3945695
OSBindings/Mac/Clock Signal.xcodeproj
Storage/Disk/DiskImage/Formats
@ -458,6 +458,7 @@
|
||||
4BFCA1271ECBE33200AC40C1 /* TestMachineZ80.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA1261ECBE33200AC40C1 /* TestMachineZ80.mm */; };
|
||||
4BFCA1291ECBE7A700AC40C1 /* zexall.com in Resources */ = {isa = PBXBuildFile; fileRef = 4BFCA1281ECBE7A700AC40C1 /* zexall.com */; };
|
||||
4BFCA12B1ECBE7C400AC40C1 /* ZexallTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */; };
|
||||
4BFDD78C1F7F2DB4008579B9 /* ImplicitSectors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -1119,6 +1120,8 @@
|
||||
4BFCA1261ECBE33200AC40C1 /* TestMachineZ80.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestMachineZ80.mm; sourceTree = "<group>"; };
|
||||
4BFCA1281ECBE7A700AC40C1 /* zexall.com */ = {isa = PBXFileReference; lastKnownFileType = file; name = zexall.com; path = Zexall/zexall.com; sourceTree = "<group>"; };
|
||||
4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZexallTests.swift; sourceTree = "<group>"; };
|
||||
4BFDD78A1F7F2DB4008579B9 /* ImplicitSectors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ImplicitSectors.hpp; sourceTree = "<group>"; };
|
||||
4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImplicitSectors.cpp; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -1469,6 +1472,7 @@
|
||||
4B45188C1F75FD1B00926311 /* Formats */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BFDD7891F7F2DB4008579B9 /* Utility */,
|
||||
4B45188D1F75FD1B00926311 /* AcornADF.cpp */,
|
||||
4B45188E1F75FD1B00926311 /* AcornADF.hpp */,
|
||||
4B45188F1F75FD1B00926311 /* CPCDSK.cpp */,
|
||||
@ -2456,6 +2460,15 @@
|
||||
path = ../../ClockReceiver;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4BFDD7891F7F2DB4008579B9 /* Utility */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BFDD78A1F7F2DB4008579B9 /* ImplicitSectors.hpp */,
|
||||
4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */,
|
||||
);
|
||||
path = Utility;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -2990,6 +3003,7 @@
|
||||
4BBFBB6C1EE8401E00C01E7A /* ZX8081.cpp in Sources */,
|
||||
4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */,
|
||||
4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */,
|
||||
4BFDD78C1F7F2DB4008579B9 /* ImplicitSectors.cpp in Sources */,
|
||||
4BC3B7521CD1956900F86E85 /* OutputShader.cpp in Sources */,
|
||||
4B5073071DDD3B9400C48FBD /* ArrayBuilder.cpp in Sources */,
|
||||
4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */,
|
||||
|
@ -8,11 +8,7 @@
|
||||
|
||||
#include "AcornADF.hpp"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include "../../Encodings/MFM/Constants.hpp"
|
||||
#include "../../Encodings/MFM/Encoder.hpp"
|
||||
#include "../../Track/TrackSerialiser.hpp"
|
||||
#include "../../Encodings/MFM/SegmentParser.hpp"
|
||||
#include "Utility/ImplicitSectors.hpp"
|
||||
|
||||
namespace {
|
||||
static const unsigned int sectors_per_track = 16;
|
||||
@ -57,54 +53,28 @@ long AcornADF::get_file_offset_for_position(unsigned int head, unsigned int posi
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> AcornADF::get_track_at_position(unsigned int head, unsigned int position) {
|
||||
std::shared_ptr<Track> track;
|
||||
uint8_t sectors[bytes_per_sector*sectors_per_track];
|
||||
|
||||
if(head >= 2) return track;
|
||||
if(head > 1) return nullptr;
|
||||
long file_offset = get_file_offset_for_position(head, position);
|
||||
|
||||
std::vector<Storage::Encodings::MFM::Sector> sectors;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock_guard(file_access_mutex_);
|
||||
fseek(file_, file_offset, SEEK_SET);
|
||||
|
||||
for(unsigned int sector = 0; sector < sectors_per_track; sector++) {
|
||||
Storage::Encodings::MFM::Sector new_sector;
|
||||
new_sector.address.track = (uint8_t)position;
|
||||
new_sector.address.side = (uint8_t)head;
|
||||
new_sector.address.sector = (uint8_t)sector;
|
||||
new_sector.size = sector_size;
|
||||
|
||||
new_sector.data.resize(bytes_per_sector);
|
||||
fread(&new_sector.data[0], 1, bytes_per_sector, file_);
|
||||
if(feof(file_))
|
||||
break;
|
||||
|
||||
sectors.push_back(std::move(new_sector));
|
||||
}
|
||||
fread(sectors, 1, sizeof(sectors), file_);
|
||||
}
|
||||
|
||||
if(sectors.size()) return Storage::Encodings::MFM::GetMFMTrackWithSectors(sectors);
|
||||
|
||||
return track;
|
||||
return track_for_sectors(sectors, (uint8_t)position, (uint8_t)head, 0, sector_size, true);
|
||||
}
|
||||
|
||||
void AcornADF::set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track) {
|
||||
std::map<size_t, Storage::Encodings::MFM::Sector> sectors =
|
||||
Storage::Encodings::MFM::sectors_from_segment(
|
||||
Storage::Disk::track_serialisation(*track, Storage::Encodings::MFM::MFMBitLength),
|
||||
true);
|
||||
|
||||
std::vector<uint8_t> parsed_track(sectors_per_track*bytes_per_sector, 0);
|
||||
for(auto &pair : sectors) {
|
||||
if(pair.second.address.sector >= sectors_per_track) continue;
|
||||
if(pair.second.size != sector_size) continue;
|
||||
memcpy(&parsed_track[pair.second.address.sector * bytes_per_sector], pair.second.data.data(), std::min(pair.second.data.size(), bytes_per_sector));
|
||||
}
|
||||
uint8_t parsed_track[bytes_per_sector*sectors_per_track];
|
||||
decode_sectors(*track, parsed_track, 0, sectors_per_track-1, sector_size, true);
|
||||
|
||||
long file_offset = get_file_offset_for_position(head, position);
|
||||
|
||||
std::lock_guard<std::mutex> lock_guard(file_access_mutex_);
|
||||
ensure_file_is_at_least_length(file_offset);
|
||||
fseek(file_, file_offset, SEEK_SET);
|
||||
fwrite(parsed_track.data(), 1, parsed_track.size(), file_);
|
||||
fwrite(parsed_track, 1, sizeof(parsed_track), file_);
|
||||
}
|
||||
|
@ -8,8 +8,13 @@
|
||||
|
||||
#include "SSD.hpp"
|
||||
|
||||
#include "../../Encodings/MFM/Encoder.hpp"
|
||||
#include "../../Encodings/MFM/Parser.hpp"
|
||||
#include "Utility/ImplicitSectors.hpp"
|
||||
|
||||
namespace {
|
||||
static const unsigned int sectors_per_track = 10;
|
||||
static const size_t bytes_per_sector = 256;
|
||||
static const unsigned int sector_size = 1;
|
||||
}
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
@ -46,57 +51,28 @@ long SSD::get_file_offset_for_position(unsigned int head, unsigned int position)
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> SSD::get_track_at_position(unsigned int head, unsigned int position) {
|
||||
std::shared_ptr<Track> track;
|
||||
uint8_t sectors[bytes_per_sector*sectors_per_track];
|
||||
|
||||
if(head >= head_count_) return track;
|
||||
if(head >= head_count_) return nullptr;
|
||||
long file_offset = get_file_offset_for_position(head, position);
|
||||
|
||||
std::vector<Storage::Encodings::MFM::Sector> sectors;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock_guard(file_access_mutex_);
|
||||
fseek(file_, get_file_offset_for_position(head, position), SEEK_SET);
|
||||
|
||||
for(int sector = 0; sector < 10; sector++) {
|
||||
Storage::Encodings::MFM::Sector new_sector;
|
||||
new_sector.address.track = (uint8_t)position;
|
||||
new_sector.address.side = 0;
|
||||
new_sector.address.sector = (uint8_t)sector;
|
||||
new_sector.size = 1;
|
||||
|
||||
new_sector.data.resize(256);
|
||||
fread(new_sector.data.data(), 1, 256, file_);
|
||||
|
||||
// zero out if this wasn't present in the disk image; it's still appropriate to put a sector
|
||||
// on disk because one will have been placed during formatting, but there's no reason to leak
|
||||
// information from outside the emulated machine's world
|
||||
if(feof(file_)) memset(new_sector.data.data(), 0, 256);
|
||||
|
||||
sectors.push_back(std::move(new_sector));
|
||||
}
|
||||
fseek(file_, file_offset, SEEK_SET);
|
||||
fread(sectors, 1, sizeof(sectors), file_);
|
||||
}
|
||||
|
||||
if(sectors.size()) return Storage::Encodings::MFM::GetFMTrackWithSectors(sectors);
|
||||
|
||||
return track;
|
||||
return track_for_sectors(sectors, (uint8_t)position, (uint8_t)head, 0, sector_size, false);
|
||||
}
|
||||
|
||||
void SSD::set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track) {
|
||||
/* std::vector<uint8_t> data;
|
||||
Storage::Encodings::MFM::Parser parser(false, track);
|
||||
for(unsigned int c = 0; c < 10; c++) {
|
||||
Storage::Encodings::MFM::Sector *sector = parser.get_sector(0, (uint8_t)position, (uint8_t)c);
|
||||
if(sector) {
|
||||
data.insert(data.end(), sector->data.begin(), sector->data.end());
|
||||
} else {
|
||||
// TODO: what's correct here? Warn the user that whatever has been written to the disk,
|
||||
// it can no longer be stored as an SSD? If so, warn them by what route?
|
||||
data.resize(data.size() + 256);
|
||||
}
|
||||
}
|
||||
uint8_t parsed_track[bytes_per_sector*sectors_per_track];
|
||||
decode_sectors(*track, parsed_track, 0, sectors_per_track-1, sector_size, false);
|
||||
|
||||
long file_offset = get_file_offset_for_position(head, position);
|
||||
|
||||
std::lock_guard<std::mutex> lock_guard(file_access_mutex_);
|
||||
ensure_file_is_at_least_length(file_offset);
|
||||
fseek(file_, file_offset, SEEK_SET);
|
||||
fwrite(data.data(), 1, data.size(), file_);*/
|
||||
fwrite(parsed_track, 1, sizeof(parsed_track), file_);
|
||||
}
|
||||
|
58
Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.cpp
Normal file
58
Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
//
|
||||
// ImplicitSectors.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 29/09/2017.
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "ImplicitSectors.hpp"
|
||||
|
||||
#include "../../../Encodings/MFM/Sector.hpp"
|
||||
#include "../../../Encodings/MFM/Encoder.hpp"
|
||||
#include "../../../Encodings/MFM/Constants.hpp"
|
||||
#include "../../../Track/TrackSerialiser.hpp"
|
||||
#include "../../../Encodings/MFM/SegmentParser.hpp"
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
std::shared_ptr<Track> Storage::Disk::track_for_sectors(uint8_t *const source, 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 = (off_t)(128 << size);
|
||||
off_t source_pointer = 0;
|
||||
for(int sector = 0; sector < 10; sector++) {
|
||||
sectors.emplace_back();
|
||||
|
||||
Storage::Encodings::MFM::Sector &new_sector = sectors.back();
|
||||
new_sector.address.track = track;
|
||||
new_sector.address.side = size;
|
||||
new_sector.address.sector = first_sector;
|
||||
first_sector++;
|
||||
new_sector.size = size;
|
||||
|
||||
new_sector.data.insert(new_sector.data.begin(), source + source_pointer, source + source_pointer + byte_size);
|
||||
source_pointer += byte_size;
|
||||
}
|
||||
|
||||
if(sectors.size()) {
|
||||
return is_double_density ? Storage::Encodings::MFM::GetMFMTrackWithSectors(sectors) : Storage::Encodings::MFM::GetFMTrackWithSectors(sectors);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Storage::Disk::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::map<size_t, Storage::Encodings::MFM::Sector> sectors =
|
||||
Storage::Encodings::MFM::sectors_from_segment(
|
||||
Storage::Disk::track_serialisation(track, is_double_density ? Storage::Encodings::MFM::MFMBitLength : Storage::Encodings::MFM::FMBitLength),
|
||||
true);
|
||||
|
||||
size_t byte_size = (size_t)(128 << sector_size);
|
||||
for(auto &pair : sectors) {
|
||||
if(pair.second.address.sector > last_sector) continue;
|
||||
if(pair.second.address.sector < first_sector) continue;
|
||||
if(pair.second.size != sector_size) continue;
|
||||
memcpy(&destination[pair.second.address.sector * byte_size], pair.second.data.data(), std::min(pair.second.data.size(), byte_size));
|
||||
}
|
||||
}
|
25
Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.hpp
Normal file
25
Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// ImplicitSectors.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 29/09/2017.
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef ImplicitSectors_hpp
|
||||
#define ImplicitSectors_hpp
|
||||
|
||||
#include "../../../Track/Track.hpp"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
std::shared_ptr<Track> track_for_sectors(uint8_t *const source, 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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ImplicitSectors_hpp */
|
Loading…
x
Reference in New Issue
Block a user