1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-22 12:33:29 +00:00

Starts trying to deal with creating a whole volume from merely a partition.

This commit is contained in:
Thomas Harte 2019-08-25 23:03:54 -04:00
parent 081316c071
commit 1a60ced61b
7 changed files with 195 additions and 11 deletions

View File

@ -39,6 +39,7 @@
#include "../../../Storage/MassStorage/SCSI/SCSI.hpp"
#include "../../../Storage/MassStorage/SCSI/DirectAccessDevice.hpp"
#include "../../../Storage/MassStorage/Encodings/MacintoshVolume.hpp"
#include "../../../Analyser/Static/Macintosh/Target.hpp"
@ -454,6 +455,10 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
// TODO: allow this only at machine startup.
if(!media.mass_storage_devices.empty()) {
const auto volume = dynamic_cast<Storage::MassStorage::Encodings::Macintosh::Volume *>(media.mass_storage_devices.front().get());
if(volume) {
volume->set_drive_type(Storage::MassStorage::Encodings::Macintosh::DriveType::SCSI);
}
hard_drive_->set_storage(media.mass_storage_devices.front());
}

View File

@ -229,6 +229,8 @@
4B7136911F789C93008B8ED9 /* SegmentParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368F1F789C93008B8ED9 /* SegmentParser.cpp */; };
4B74CF812312FA9C00500CE8 /* HFV.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CF802312FA9C00500CE8 /* HFV.cpp */; };
4B74CF822312FA9C00500CE8 /* HFV.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CF802312FA9C00500CE8 /* HFV.cpp */; };
4B74CF85231370BC00500CE8 /* MacintoshVolume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CF83231370BC00500CE8 /* MacintoshVolume.cpp */; };
4B74CF86231370BC00500CE8 /* MacintoshVolume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CF83231370BC00500CE8 /* MacintoshVolume.cpp */; };
4B7913CC1DFCD80E00175A82 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7913CA1DFCD80E00175A82 /* Video.cpp */; };
4B79A5011FC913C900EEDAD5 /* MSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B79A4FF1FC913C900EEDAD5 /* MSX.cpp */; };
4B79E4441E3AF38600141F11 /* cassette.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4411E3AF38600141F11 /* cassette.png */; };
@ -988,6 +990,8 @@
4B7136901F789C93008B8ED9 /* SegmentParser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SegmentParser.hpp; sourceTree = "<group>"; };
4B74CF7F2312FA9C00500CE8 /* HFV.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = HFV.hpp; sourceTree = "<group>"; };
4B74CF802312FA9C00500CE8 /* HFV.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HFV.cpp; sourceTree = "<group>"; };
4B74CF83231370BC00500CE8 /* MacintoshVolume.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MacintoshVolume.cpp; path = Encodings/MacintoshVolume.cpp; sourceTree = "<group>"; };
4B74CF84231370BC00500CE8 /* MacintoshVolume.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = MacintoshVolume.hpp; path = Encodings/MacintoshVolume.hpp; sourceTree = "<group>"; };
4B77069C1EC904570053B588 /* Z80.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Z80.hpp; path = Z80/Z80.hpp; sourceTree = "<group>"; };
4B770A961FE9EE770026DC70 /* CompoundSource.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CompoundSource.hpp; sourceTree = "<group>"; };
4B7913CA1DFCD80E00175A82 /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Video.cpp; path = Electron/Video.cpp; sourceTree = "<group>"; };
@ -2266,6 +2270,8 @@
4B6AAEA3230E3E1D0078E864 /* MassStorageDevice.hpp */,
4B74CF7E2312FA9C00500CE8 /* Formats */,
4B6AAEA5230E40250078E864 /* SCSI */,
4B74CF83231370BC00500CE8 /* MacintoshVolume.cpp */,
4B74CF84231370BC00500CE8 /* MacintoshVolume.hpp */,
);
path = MassStorage;
sourceTree = "<group>";
@ -4083,6 +4089,7 @@
4B055ACD1FAE9B030060FFFF /* Keyboard.cpp in Sources */,
4B055AB21FAE860F0060FFFF /* CommodoreTAP.cpp in Sources */,
4B055ADF1FAE9B4C0060FFFF /* IRQDelegatePortHandler.cpp in Sources */,
4B74CF86231370BC00500CE8 /* MacintoshVolume.cpp in Sources */,
4BD424E02193B5340097291A /* TextureTarget.cpp in Sources */,
4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */,
4B055AE01FAE9B660060FFFF /* CRT.cpp in Sources */,
@ -4197,6 +4204,7 @@
4BC76E691C98E31700E6EF73 /* FIRFilter.cpp in Sources */,
4B3BF5B01F146265005B6C36 /* CSW.cpp in Sources */,
4BCE0060227D39AB000CA200 /* Video.cpp in Sources */,
4B74CF85231370BC00500CE8 /* MacintoshVolume.cpp in Sources */,
4B4518A51F75FD1C00926311 /* SSD.cpp in Sources */,
4B55CE5F1C3B7D960093A61B /* MachineDocument.swift in Sources */,
4B2B3A4C1F9B8FA70062DABF /* MemoryFuzzer.cpp in Sources */,

View File

@ -72,9 +72,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableAddressSanitizer = "YES"
enableASanStackUseAfterReturn = "YES"
enableUBSanitizer = "YES"
disableMainThreadChecker = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"

View File

@ -0,0 +1,64 @@
//
// MacintoshVolume.cpp
// Clock Signal
//
// Created by Thomas Harte on 25/08/2019.
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#include "MacintoshVolume.hpp"
using namespace Storage::MassStorage::Encodings::Macintosh;
void Mapper::set_drive_type(DriveType drive_type, size_t number_of_blocks) {
drive_type_ = drive_type;
number_of_blocks_ = number_of_blocks;
}
size_t Mapper::get_number_of_blocks() {
return number_of_blocks_ + 5;
}
ssize_t Mapper::to_source_address(size_t address) {
/*
Reserve one block at the start of the device
for a partition map.
TODO: and four or so more for a driver?
*/
return ssize_t(address) - 5;
}
std::vector<uint8_t> Mapper::convert_source_block(ssize_t source_address, std::vector<uint8_t> source_data) {
switch(source_address) {
case -5: {
uint32_t total_device_blocks = uint32_t(number_of_blocks_ + 5);
/* The driver descriptor. */
std::vector<uint8_t> driver_description = {
0x45, 0x52, /* device signature */
0x02, 0x00, /* block size, in bytes */
uint8_t(total_device_blocks >> 24),
uint8_t(total_device_blocks >> 16),
uint8_t(total_device_blocks >> 8),
uint8_t(total_device_blocks),
/* number of blocks on device */
0x00, 0x00, /* reserved */
0x00, 0x00, /* reserved */
0x00, 0x00, /* reserved */
0x00, 0x01, /* number of device descriptor entries */
0x00, 0x01, /* first device descriptor's starting block */
0x00, 0x04, /* size of device driver */
0x00, 0x01, /* operating system (MacOS = 1) */
};
driver_description.resize(512);
return driver_description;
}
default: return source_data;
}
}

View File

@ -0,0 +1,87 @@
//
// MacintoshVolume.hpp
// Clock Signal
//
// Created by Thomas Harte on 25/08/2019.
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef MacintoshVolume_hpp
#define MacintoshVolume_hpp
#include <vector>
#include <cstdint>
namespace Storage {
namespace MassStorage {
namespace Encodings {
namespace Macintosh {
enum class DriveType {
SCSI
};
/*!
On the Macintosh life is slightly complicated by Apple's
decision to include device drivers on mass storage drives
themselves therefore a mass-storage device that is
connected by SCSI will have different preliminary data on it
than the same volume connected by ATA or as an HD20.
Mass storage devices that respond to @c Volume can be made
to provide the proper whole-volume encoding necessary to
impersonate different types of Macintosh drive.
*/
class Volume {
public:
virtual void set_drive_type(DriveType type) = 0;
};
/*!
A Mapper can used by a mass-storage device that knows the
contents of an HFS or MFS partition to provide the conversion
necessary to a particular type of drive.
*/
class Mapper {
public:
/*!
Sets the drive type to map to and the number of blocks in the underlying partition.
*/
void set_drive_type(DriveType, size_t number_of_blocks);
/*!
Maps from a mass-storage device address to an address
in the underlying [H/M]FS partition.
*/
ssize_t to_source_address(size_t address);
/*!
Converts from a source data block to one properly encoded for the drive type.
Expected usage:
const size_t source_address = mapper.to_source_address(unit_address);
if(is_in_range_for_partition(source_address)) {
return mapper.convert_source_block(source_address, get_block_contents(source_address));
} else {
return mapper.convert_source_block(source_address);
}
*/
std::vector<uint8_t> convert_source_block(ssize_t source_address, std::vector<uint8_t> source_data = {});
/*!
@returns The total number of blocks on the entire volume.
*/
size_t get_number_of_blocks();
private:
DriveType drive_type_;
size_t number_of_blocks_;
};
}
}
}
}
#endif /* MacintoshVolume_hpp */

View File

@ -23,17 +23,29 @@ size_t HFV::get_block_size() {
}
size_t HFV::get_number_of_blocks() {
return size_t(file_.stats().st_size) / get_block_size();
return mapper_.get_number_of_blocks();
}
std::vector<uint8_t> HFV::get_block(size_t address) {
const long file_offset = long(get_block_size() * address);
file_.seek(file_offset, SEEK_SET);
return file_.read(get_block_size());
const auto source_address = mapper_.to_source_address(address);
if(source_address >= 0 && size_t(source_address)*get_block_size() < size_t(file_.stats().st_size)) {
const long file_offset = long(get_block_size()) * long(source_address);
file_.seek(file_offset, SEEK_SET);
return mapper_.convert_source_block(source_address, file_.read(get_block_size()));
} else {
return mapper_.convert_source_block(source_address);
}
}
void HFV::set_block(size_t address, const std::vector<uint8_t> &contents) {
const long file_offset = long(get_block_size() * address);
file_.seek(file_offset, SEEK_SET);
file_.write(contents);
const auto source_address = mapper_.to_source_address(address);
if(source_address >= 0 && size_t(source_address)*get_block_size() < size_t(file_.stats().st_size)) {
const long file_offset = long(get_block_size()) * long(source_address);
file_.seek(file_offset, SEEK_SET);
file_.write(contents);
}
}
void HFV::set_drive_type(Encodings::Macintosh::DriveType drive_type) {
mapper_.set_drive_type(drive_type, size_t(file_.stats().st_size) / get_block_size());
}

View File

@ -11,26 +11,36 @@
#include "../MassStorageDevice.hpp"
#include "../../FileHolder.hpp"
#include "../Encodings/MacintoshVolume.hpp"
namespace Storage {
namespace MassStorage {
/*!
Provides a @c MassStorageDevice containing an HFV image, which is a sector dump of
a Macintosh drive that is not the correct size to be a floppy disk.
the HFS volume of a Macintosh drive that is not the correct size to be a floppy disk.
*/
class HFV: public MassStorageDevice {
class HFV: public MassStorageDevice, public Encodings::Macintosh::Volume {
public:
/*!
Constructs an HFV with the contents of the file named @c file_name.
Raises an exception if the file name doesn't appear to identify a valid
Macintosh mass storage image.
*/
HFV(const std::string &file_name);
private:
FileHolder file_;
Encodings::Macintosh::Mapper mapper_;
/* MassStorageDevices overrides. */
size_t get_block_size() final;
size_t get_number_of_blocks() final;
std::vector<uint8_t> get_block(size_t address) final;
void set_block(size_t address, const std::vector<uint8_t> &) final;
/* Encodings::Macintosh::Volume overrides. */
void set_drive_type(Encodings::Macintosh::DriveType) final;
};
}