mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Starts trying to deal with creating a whole volume from merely a partition.
This commit is contained in:
parent
081316c071
commit
1a60ced61b
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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 */,
|
||||
|
@ -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"
|
||||
|
64
Storage/MassStorage/Encodings/MacintoshVolume.cpp
Normal file
64
Storage/MassStorage/Encodings/MacintoshVolume.cpp
Normal 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;
|
||||
}
|
||||
}
|
87
Storage/MassStorage/Encodings/MacintoshVolume.hpp
Normal file
87
Storage/MassStorage/Encodings/MacintoshVolume.hpp
Normal 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 */
|
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user