1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Merge branch 'master' into DragAndDropState

This commit is contained in:
Thomas Harte 2021-05-16 20:42:44 -04:00
commit 5483f979dc
10 changed files with 138 additions and 44 deletions

View File

@ -55,6 +55,7 @@
// Mass Storage Devices (i.e. usually, hard disks)
#include "../../Storage/MassStorage/Formats/DAT.hpp"
#include "../../Storage/MassStorage/Formats/DSK.hpp"
#include "../../Storage/MassStorage/Formats/HFV.hpp"
// State Snapshots
@ -144,7 +145,8 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
TargetPlatform::AmstradCPC | TargetPlatform::Oric | TargetPlatform::ZXSpectrum) // DSK (Amstrad CPC, etc)
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::AppleDSK>, TargetPlatform::DiskII) // DSK (Apple II)
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // DSK (Macintosh, floppy disk)
Format("dsk", result.mass_storage_devices, MassStorage::HFV, TargetPlatform::Macintosh) // DSK (Macintosh, hard disk)
Format("dsk", result.mass_storage_devices, MassStorage::HFV, TargetPlatform::Macintosh) // DSK (Macintosh, hard disk, single volume image)
Format("dsk", result.mass_storage_devices, MassStorage::DSK, TargetPlatform::Macintosh) // DSK (Macintosh, hard disk, full device image)
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::MSXDSK>, TargetPlatform::MSX) // DSK (MSX)
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::OricMFMDSK>, TargetPlatform::Oric) // DSK (Oric)
Format("g64", result.disks, Disk::DiskImageHolder<Storage::Disk::G64>, TargetPlatform::Commodore) // G64

View File

@ -551,6 +551,8 @@
4B92E26B234AE35100CD6D1B /* MFP68901.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B92E268234AE35000CD6D1B /* MFP68901.cpp */; };
4B92EACA1B7C112B00246143 /* 6502TimingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */; };
4B9378E422A199C600973513 /* Audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9378E222A199C600973513 /* Audio.cpp */; };
4B96F7CE263E33B10092AEE1 /* DSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B96F7CC263E33B10092AEE1 /* DSK.cpp */; };
4B96F7CF263E33B10092AEE1 /* DSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B96F7CC263E33B10092AEE1 /* DSK.cpp */; };
4B98A05E1FFAD3F600ADF63B /* CSROMFetcher.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */; };
4B98A05F1FFAD62400ADF63B /* CSROMFetcher.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */; };
4B98A0611FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B98A0601FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm */; };
@ -1524,6 +1526,9 @@
4B9378E322A199C600973513 /* Audio.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Audio.hpp; sourceTree = "<group>"; };
4B95FA9C1F11893B0008E395 /* ZX8081OptionsPanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZX8081OptionsPanel.swift; sourceTree = "<group>"; };
4B961408222760E0001A7BF2 /* Screenshot.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Screenshot.hpp; sourceTree = "<group>"; };
4B96F7CB263E30B00092AEE1 /* RawSectorDump.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RawSectorDump.hpp; sourceTree = "<group>"; };
4B96F7CC263E33B10092AEE1 /* DSK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DSK.cpp; sourceTree = "<group>"; };
4B96F7CD263E33B10092AEE1 /* DSK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DSK.hpp; sourceTree = "<group>"; };
4B98A05C1FFAD3F600ADF63B /* CSROMFetcher.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CSROMFetcher.hpp; sourceTree = "<group>"; };
4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CSROMFetcher.mm; sourceTree = "<group>"; };
4B98A0601FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MSXStaticAnalyserTests.mm; sourceTree = "<group>"; };
@ -2969,10 +2974,13 @@
4B74CF7E2312FA9C00500CE8 /* Formats */ = {
isa = PBXGroup;
children = (
4B74CF7F2312FA9C00500CE8 /* HFV.hpp */,
4B74CF802312FA9C00500CE8 /* HFV.cpp */,
4BE8EB6425C750B50040BC40 /* DAT.cpp */,
4BE8EB6525C750B50040BC40 /* DAT.hpp */,
4B96F7CC263E33B10092AEE1 /* DSK.cpp */,
4B96F7CD263E33B10092AEE1 /* DSK.hpp */,
4B74CF802312FA9C00500CE8 /* HFV.cpp */,
4B74CF7F2312FA9C00500CE8 /* HFV.hpp */,
4B96F7CB263E30B00092AEE1 /* RawSectorDump.hpp */,
);
path = Formats;
sourceTree = "<group>";
@ -5238,6 +5246,7 @@
4B1B58F7246CC4E8009C171E /* State.cpp in Sources */,
4B0ACC03237756F6008902D0 /* Line.cpp in Sources */,
4B055AB11FAE86070060FFFF /* Tape.cpp in Sources */,
4B96F7CF263E33B10092AEE1 /* DSK.cpp in Sources */,
4B2B946626377C0200E7097C /* SZX.cpp in Sources */,
4BEDA43225B3C700000C2DBD /* Executor.cpp in Sources */,
4BC1317B2346DF2B00E4FF3D /* MSA.cpp in Sources */,
@ -5544,6 +5553,7 @@
4B89453E201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
4BF8D4D5251C11DD00BBE21B /* 65816Storage.cpp in Sources */,
4B0ACC2823775819008902D0 /* DMAController.cpp in Sources */,
4B96F7CE263E33B10092AEE1 /* DSK.cpp in Sources */,
4BC131702346DE5000E4FF3D /* StaticAnalyser.cpp in Sources */,
4B37EE821D7345A6006A09A4 /* BinaryDump.cpp in Sources */,
4BCE0053227CE8CA000CA200 /* AppleII.cpp in Sources */,

View File

@ -1,6 +1,6 @@
![Clock Signal Application Icon](READMEImages/Icon.png)
# Clock Signal
Clock Signal ('CLK') is an emulator for tourists that seeks to be invisible. Users directly launch classic software, avoiding the learning curve associated with emulators and with classic machines.
Clock Signal ('CLK') is an emulator for tourists that seeks to be invisible. Users directly launch classic software, avoiding the learning curves associated with emulators and with classic machines.
This emulator seeks to offer:
* single-click load of any piece of source media for any supported platform;

View File

@ -10,32 +10,13 @@
using namespace Storage::MassStorage;
DAT::DAT(const std::string &file_name) : file_(file_name) {
// Is the file a multiple of 256 bytes in size?
const auto file_size = file_.stats().st_size;
if(file_size & 255) throw std::exception();
// Does it contain the 'Hugo' signature?
file_.seek(0x201, SEEK_SET);
if(!file_.check_signature("Hugo")) {
DAT::DAT(const std::string &file_name) : RawSectorDump(file_name) {
// Does the third sector contain the 'Hugo' signature?
const auto sector3 = get_block(2);
if(sector3.size() != 256) {
throw std::exception();
}
if(sector3[1] != 'H' || sector3[2] != 'u' || sector3[3] != 'g' || sector3[4] != 'o') {
throw std::exception();
}
}
size_t DAT::get_block_size() {
return 256;
}
size_t DAT::get_number_of_blocks() {
return size_t(file_.stats().st_size) / 256;
}
std::vector<uint8_t> DAT::get_block(size_t address) {
file_.seek(long(address * 256), SEEK_SET);
return file_.read(256);
}
void DAT::set_block(size_t address, const std::vector<uint8_t> &contents) {
file_.seek(long(address * 256), SEEK_SET);
file_.write(contents);
}

View File

@ -9,8 +9,7 @@
#ifndef MassStorage_DAT_hpp
#define MassStorage_DAT_hpp
#include "../MassStorageDevice.hpp"
#include "../../FileHolder.hpp"
#include "RawSectorDump.hpp"
namespace Storage {
namespace MassStorage {
@ -20,18 +19,9 @@ namespace MassStorage {
sector dump of an ADFS volume. It will be validated for an ADFS catalogue and communicate
in 256-byte blocks.
*/
class DAT: public MassStorageDevice {
class DAT: public RawSectorDump<256> {
public:
DAT(const std::string &file_name);
private:
FileHolder file_;
/* 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;
};
}

View File

@ -0,0 +1,23 @@
//
// DSK.cpp
// Clock Signal
//
// Created by Thomas Harte on 01/05/2021.
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#include "DSK.hpp"
using namespace Storage::MassStorage;
DSK::DSK(const std::string &file_name) : RawSectorDump(file_name) {
// Minimum validation: check the first sector for a device signature,
// with 512-byte blocks.
const auto sector = get_block(0);
if(sector.size() != 512) {
throw std::exception();
}
if(sector[0] != 0x45 || sector[1] != 0x52 || sector[2] != 0x02 || sector[3] != 0x00) {
throw std::exception();
}
}

View File

@ -0,0 +1,30 @@
//
// DSK.hpp
// Clock Signal
//
// Created by Thomas Harte on 01/05/2021.
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef MassStorage_DSK_hpp
#define MassStorage_DSK_hpp
#include "RawSectorDump.hpp"
namespace Storage {
namespace MassStorage {
/*!
Provides a @c MassStorageDevice containing a Macintosh DSK image, which is just a
sector dump of an entire HFS drive. It will be validated for an Apple-style partition map and communicate
in 512-byte blocks.
*/
class DSK: public RawSectorDump<512> {
public:
DSK(const std::string &file_name);
};
}
}
#endif /* MassStorage_DSK_hpp */

View File

@ -15,7 +15,10 @@ HFV::HFV(const std::string &file_name) : file_(file_name) {
const auto file_size = file_.stats().st_size;
if(file_size & 511 || file_size <= 800*1024) throw std::exception();
// TODO: check filing system for MFS, HFS or HFS+.
// Is this an HFS volume?
// TODO: check filing system for MFS or HFS+.
const auto prefix = file_.read(2);
if(prefix[0] != 'L' || prefix[1] != 'K') throw std::exception();
}
size_t HFV::get_block_size() {

View File

@ -0,0 +1,55 @@
//
// RawSectorDump.hpp
// Clock Signal
//
// Created by Thomas Harte on 01/05/2021.
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef RawSectorDump_h
#define RawSectorDump_h
#include "../MassStorageDevice.hpp"
#include "../../FileHolder.hpp"
#include <cassert>
namespace Storage {
namespace MassStorage {
template <size_t sector_size> class RawSectorDump: public MassStorageDevice {
public:
RawSectorDump(const std::string &file_name) : file_(file_name) {
// Is the file a multiple of sector_size bytes in size?
const auto file_size = size_t(file_.stats().st_size);
if(file_size % sector_size) throw std::exception();
}
/* MassStorageDevices overrides. */
size_t get_block_size() final {
return sector_size;
}
size_t get_number_of_blocks() final {
return size_t(file_.stats().st_size) / sector_size;
}
std::vector<uint8_t> get_block(size_t address) final {
file_.seek(long(address * sector_size), SEEK_SET);
return file_.read(sector_size);
}
void set_block(size_t address, const std::vector<uint8_t> &contents) final {
assert(contents.size() == sector_size);
file_.seek(long(address * sector_size), SEEK_SET);
file_.write(contents);
}
private:
FileHolder file_;
};
}
}
#endif /* RawSectorDump_h */

View File

@ -19,7 +19,7 @@ bool DirectAccessDevice::read(const Target::CommandState &state, Target::Respond
if(!device_) return false;
const auto specs = state.read_write_specs();
LOG("Read: " << specs.number_of_blocks << " from " << specs.address);
LOG("Read: " << std::dec << specs.number_of_blocks << " from " << specs.address);
std::vector<uint8_t> output = device_->get_block(specs.address);
for(uint32_t offset = 1; offset < specs.number_of_blocks; ++offset) {