1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 16:31:31 +00:00

Merge pull request #211 from TomHarte/HFE

Introduces support for the HFE file format.
This commit is contained in:
Thomas Harte 2017-08-17 22:43:23 -04:00 committed by GitHub
commit 5bdd24d93f
5 changed files with 165 additions and 1 deletions

View File

@ -442,6 +442,7 @@
4BF8295D1D8F048B001BAE39 /* MFM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8295B1D8F048B001BAE39 /* MFM.cpp */; };
4BF829631D8F536B001BAE39 /* SSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF829611D8F536B001BAE39 /* SSD.cpp */; };
4BF829661D8F732B001BAE39 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF829641D8F732B001BAE39 /* Disk.cpp */; };
4BFB9FAE1F467D3A00960122 /* HFE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFB9FAC1F467D3A00960122 /* HFE.cpp */; };
4BFCA1201ECBDC1500AC40C1 /* Z80AllRAM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA11D1ECBD9BD00AC40C1 /* Z80AllRAM.cpp */; };
4BFCA1241ECBDCB400AC40C1 /* AllRAMProcessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */; };
4BFCA1271ECBE33200AC40C1 /* TestMachineZ80.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA1261ECBE33200AC40C1 /* TestMachineZ80.mm */; };
@ -1067,6 +1068,8 @@
4BF829641D8F732B001BAE39 /* Disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Disk.cpp; path = ../../StaticAnalyser/Acorn/Disk.cpp; sourceTree = "<group>"; };
4BF829651D8F732B001BAE39 /* Disk.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Disk.hpp; path = ../../StaticAnalyser/Acorn/Disk.hpp; sourceTree = "<group>"; };
4BF829681D8F7361001BAE39 /* File.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = File.hpp; path = ../../StaticAnalyser/Acorn/File.hpp; sourceTree = "<group>"; };
4BFB9FAC1F467D3A00960122 /* HFE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HFE.cpp; sourceTree = "<group>"; };
4BFB9FAD1F467D3A00960122 /* HFE.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = HFE.hpp; sourceTree = "<group>"; };
4BFCA11D1ECBD9BD00AC40C1 /* Z80AllRAM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Z80AllRAM.cpp; path = Z80/Z80AllRAM.cpp; sourceTree = "<group>"; };
4BFCA11E1ECBD9BD00AC40C1 /* Z80AllRAM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Z80AllRAM.hpp; path = Z80/Z80AllRAM.hpp; sourceTree = "<group>"; };
4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AllRAMProcessor.cpp; sourceTree = "<group>"; };
@ -1587,6 +1590,8 @@
4BF829621D8F536B001BAE39 /* SSD.hpp */,
4B838F1D1F35FDCD0016B5E6 /* CPCDSK.cpp */,
4B838F1E1F35FDCD0016B5E6 /* CPCDSK.hpp */,
4BFB9FAC1F467D3A00960122 /* HFE.cpp */,
4BFB9FAD1F467D3A00960122 /* HFE.hpp */,
);
path = Formats;
sourceTree = "<group>";
@ -2819,6 +2824,7 @@
4B2A539F1D117D36003C6002 /* CSAudioQueue.m in Sources */,
4B37EE821D7345A6006A09A4 /* BinaryDump.cpp in Sources */,
4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */,
4BFB9FAE1F467D3A00960122 /* HFE.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -245,6 +245,22 @@
<key>NSDocumentClass</key>
<string>$(PRODUCT_MODULE_NAME).MachineDocument</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>hfe</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>floppy35</string>
<key>CFBundleTypeName</key>
<string>HxC Disk Image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSTypeIsPackage</key>
<integer>0</integer>
<key>NSDocumentClass</key>
<string>$(PRODUCT_MODULE_NAME).MachineDocument</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>

View File

@ -27,6 +27,7 @@
#include "../Storage/Disk/Formats/CPCDSK.hpp"
#include "../Storage/Disk/Formats/D64.hpp"
#include "../Storage/Disk/Formats/G64.hpp"
#include "../Storage/Disk/Formats/HFE.hpp"
#include "../Storage/Disk/Formats/OricMFMDSK.hpp"
#include "../Storage/Disk/Formats/SSD.hpp"
@ -48,7 +49,8 @@ enum class TargetPlatform: TargetPlatformType {
Oric = 1 << 4,
ZX8081 = 1 << 5,
AllTape = Acorn | Commodore | Oric | ZX8081 | AmstradCPC,
AllTape = Acorn | AmstradCPC | Commodore | Oric | ZX8081,
AllDisk = Acorn | AmstradCPC | Commodore | Oric,
};
using namespace StaticAnalyser;
@ -95,6 +97,7 @@ static Media GetMediaAndPlatforms(const char *file_name, TargetPlatformType &pot
Format("dsk", result.disks, Disk::CPCDSK, TargetPlatform::AmstradCPC) // DSK (Amstrad CPC)
Format("dsk", result.disks, Disk::OricMFMDSK, TargetPlatform::Oric) // DSK (Oric)
Format("g64", result.disks, Disk::G64, TargetPlatform::Commodore) // G64
Format("hfe", result.disks, Disk::HFE, TargetPlatform::AmstradCPC) // HFE (TODO: plus other target platforms)
Format("o", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // O
Format("p", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P
Format("p81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P81

View File

@ -0,0 +1,86 @@
//
// HFE.cpp
// Clock Signal
//
// Created by Thomas Harte on 17/08/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "HFE.hpp"
#include "../PCMTrack.hpp"
using namespace Storage::Disk;
HFE::HFE(const char *file_name) :
Storage::FileHolder(file_name) {
if(!check_signature("HXCPICFE", 8)) throw ErrorNotHFE;
if(fgetc(file_)) throw ErrorNotHFE;
track_count_ = (unsigned int)fgetc(file_);
head_count_ = (unsigned int)fgetc(file_);
fseek(file_, 7, SEEK_CUR);
track_list_offset_ = (long)fgetc16le() << 9;
}
HFE::~HFE() {
}
unsigned int HFE::get_head_position_count() {
return track_count_;
}
unsigned int HFE::get_head_count() {
return head_count_;
}
bool HFE::get_is_read_only() {
return true;
}
std::shared_ptr<Track> HFE::get_uncached_track_at_position(unsigned int head, unsigned int position) {
// Get track position and length from the lookup table; data is then always interleaved
// based on an assumption of two heads.
fseek(file_, track_list_offset_ + position * 4, SEEK_SET);
long track_offset = (long)fgetc16le() << 9;
uint16_t track_length = fgetc16le();
fseek(file_, track_offset, SEEK_SET);
if(head) fseek(file_, 256, SEEK_CUR);
PCMSegment segment;
uint16_t side_length = track_length / 2;
segment.data.resize(side_length);
segment.number_of_bits = side_length * 8;
uint16_t c = 0;
while(c < side_length) {
uint16_t length = (uint16_t)std::min(256, side_length - c);
fread(&segment.data[c], 1, length, file_);
c += length;
fseek(file_, 256, SEEK_CUR);
}
// Flip bytes; HFE's preference is that the least-significant bit
// is serialised first, but PCMTrack posts the most-significant first.
for(size_t i = 0; i < segment.data.size(); i++) {
uint8_t original = segment.data[i];
uint8_t flipped_byte =
(uint8_t)(
((original & 0x01) << 7) |
((original & 0x02) << 5) |
((original & 0x04) << 3) |
((original & 0x08) << 1) |
((original & 0x10) >> 1) |
((original & 0x20) >> 3) |
((original & 0x40) >> 5) |
((original & 0x80) >> 7)
);
segment.data[i] = flipped_byte;
}
std::shared_ptr<Track> track(new PCMTrack(segment));
return track;
}

View File

@ -0,0 +1,53 @@
//
// HFE.hpp
// Clock Signal
//
// Created by Thomas Harte on 17/08/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef HFE_hpp
#define HFE_hpp
#include "../Disk.hpp"
#include "../../FileHolder.hpp"
namespace Storage {
namespace Disk {
/*!
Provies a @c Disk containing an HFE disk image a bit stream representation of a floppy.
*/
class HFE: public Disk, public Storage::FileHolder {
public:
/*!
Construct an @c SSD containing content from the file with name @c file_name.
@throws ErrorCantOpen if this file can't be opened.
@throws ErrorNotSSD if the file doesn't appear to contain a .SSD format image.
*/
HFE(const char *file_name);
~HFE();
enum {
ErrorNotHFE,
};
// implemented to satisfy @c Disk
unsigned int get_head_position_count();
unsigned int get_head_count();
bool get_is_read_only();
private:
std::shared_ptr<Track> get_uncached_track_at_position(unsigned int head, unsigned int position);
unsigned int head_count_;
unsigned int track_count_;
long track_list_offset_;
};
}
}
#endif /* HFE_hpp */