1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

Factors out the more egregious similarities between ADF and SSD.

This commit is contained in:
Thomas Harte 2017-09-29 22:07:23 -04:00
parent 19eb975c73
commit 5dd3945695
5 changed files with 121 additions and 78 deletions

View File

@ -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 */,

View File

@ -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_);
}

View 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_);
}

View 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));
}
}

View 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 */