1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-11 04:28:58 +00:00

Merge pull request #675 from TomHarte/STFileFormat

Adds support for .ST files.
This commit is contained in:
Thomas Harte 2019-11-12 23:32:47 -05:00 committed by GitHub
commit efdd27a435
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 119 additions and 22 deletions

View File

@ -46,6 +46,7 @@
#include "../../Storage/Disk/DiskImage/Formats/NIB.hpp"
#include "../../Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp"
#include "../../Storage/Disk/DiskImage/Formats/SSD.hpp"
#include "../../Storage/Disk/DiskImage/Formats/ST.hpp"
#include "../../Storage/Disk/DiskImage/Formats/WOZ.hpp"
// Mass Storage Devices (i.e. usually, hard disks)
@ -145,6 +146,7 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
Format("sg", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Sega) // SG
Format("sms", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Sega) // SMS
Format("ssd", result.disks, Disk::DiskImageHolder<Storage::Disk::SSD>, TargetPlatform::Acorn) // SSD
Format("st", result.disks, Disk::DiskImageHolder<Storage::Disk::ST>, TargetPlatform::AtariST) // ST
Format("tap", result.tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP (Commodore)
Format("tap", result.tapes, Tape::OricTAP, TargetPlatform::Oric) // TAP (Oric)
Format("tsx", result.tapes, Tape::TZX, TargetPlatform::MSX) // TSX

View File

@ -71,8 +71,8 @@ class ConcreteMachine:
Memory::Fuzz(ram_);
std::vector<ROMMachine::ROM> rom_descriptions = {
// {"AtariST", "the UK TOS 1.00 ROM", "tos100.img", 192*1024, 0x1a586c64}
{"AtariST", "the UK TOS 1.04 ROM", "tos104.img", 192*1024, 0xa50d1d43}
{"AtariST", "the UK TOS 1.00 ROM", "tos100.img", 192*1024, 0x1a586c64}
// {"AtariST", "the UK TOS 1.04 ROM", "tos104.img", 192*1024, 0xa50d1d43}
};
const auto roms = rom_fetcher(rom_descriptions);
if(!roms[0]) {

View File

@ -707,6 +707,8 @@
4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A539A1D117D36003C6002 /* CSAtari2600.mm */; };
4BDB61EC203285AE0048AF91 /* Atari2600OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsPanel.swift */; };
4BDDBA991EF3451200347E61 /* Z80MachineCycleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */; };
4BE0A3EE237BB170002AB46F /* ST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BE0A3EC237BB170002AB46F /* ST.cpp */; };
4BE0A3EF237BB170002AB46F /* ST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BE0A3EC237BB170002AB46F /* ST.cpp */; };
4BE76CF922641ED400ACD6FA /* QLTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BE76CF822641ED300ACD6FA /* QLTests.mm */; };
4BE90FFD22D5864800FB464D /* MacintoshVideoTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BE90FFC22D5864800FB464D /* MacintoshVideoTests.mm */; };
4BE9A6B11EDE293000CBCB47 /* zexdoc.com in Resources */ = {isa = PBXBuildFile; fileRef = 4BE9A6B01EDE293000CBCB47 /* zexdoc.com */; };
@ -1573,6 +1575,8 @@
4BDB3D8522833321002D3CEE /* Keyboard.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = "<group>"; };
4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMMachine.hpp; sourceTree = "<group>"; };
4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MachineCycleTests.swift; sourceTree = "<group>"; };
4BE0A3EC237BB170002AB46F /* ST.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ST.cpp; sourceTree = "<group>"; };
4BE0A3ED237BB170002AB46F /* ST.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ST.hpp; sourceTree = "<group>"; };
4BE3231220532443006EF799 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
4BE32313205327D7006EF799 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
4BE32314205328FF006EF799 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
@ -2124,36 +2128,38 @@
isa = PBXGroup;
children = (
4B45188D1F75FD1B00926311 /* AcornADF.cpp */,
4B0333AD2094081A0050B93D /* AppleDSK.cpp */,
4B45188F1F75FD1B00926311 /* CPCDSK.cpp */,
4B4518911F75FD1B00926311 /* D64.cpp */,
4BAF2B4C2004580C00480230 /* DMK.cpp */,
4B4518931F75FD1B00926311 /* G64.cpp */,
4B4518951F75FD1B00926311 /* HFE.cpp */,
4BB4BFAE22A42F290069048D /* MacintoshIMG.cpp */,
4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */,
4BC131782346DF2B00E4FF3D /* MSA.cpp */,
4BEBFB4B2002C4BF000708CC /* MSXDSK.cpp */,
4B0F94FC208C1A1600FE41D9 /* NIB.cpp */,
4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */,
4B4518991F75FD1B00926311 /* SSD.cpp */,
4B6ED2EE208E2F8A0047B343 /* WOZ.cpp */,
4B45188E1F75FD1B00926311 /* AcornADF.hpp */,
4B0333AD2094081A0050B93D /* AppleDSK.cpp */,
4B0333AE2094081A0050B93D /* AppleDSK.hpp */,
4B45188F1F75FD1B00926311 /* CPCDSK.cpp */,
4B4518901F75FD1B00926311 /* CPCDSK.hpp */,
4B4518911F75FD1B00926311 /* D64.cpp */,
4B4518921F75FD1B00926311 /* D64.hpp */,
4BAF2B4C2004580C00480230 /* DMK.cpp */,
4BAF2B4D2004580C00480230 /* DMK.hpp */,
4B4518931F75FD1B00926311 /* G64.cpp */,
4B4518941F75FD1B00926311 /* G64.hpp */,
4B4518951F75FD1B00926311 /* HFE.cpp */,
4B4518961F75FD1B00926311 /* HFE.hpp */,
4BB4BFAE22A42F290069048D /* MacintoshIMG.cpp */,
4BB4BFAF22A42F290069048D /* MacintoshIMG.hpp */,
4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */,
4B58601D1F806AB200AEE2E3 /* MFMSectorDump.hpp */,
4BC131782346DF2B00E4FF3D /* MSA.cpp */,
4BC131792346DF2B00E4FF3D /* MSA.hpp */,
4BEBFB4B2002C4BF000708CC /* MSXDSK.cpp */,
4BEBFB4C2002C4BF000708CC /* MSXDSK.hpp */,
4B0F94FC208C1A1600FE41D9 /* NIB.cpp */,
4B0F94FD208C1A1600FE41D9 /* NIB.hpp */,
4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */,
4B4518981F75FD1B00926311 /* OricMFMDSK.hpp */,
4B4518991F75FD1B00926311 /* SSD.cpp */,
4B45189A1F75FD1B00926311 /* SSD.hpp */,
4B6ED2EF208E2F8A0047B343 /* WOZ.hpp */,
4BE0A3EC237BB170002AB46F /* ST.cpp */,
4BE0A3ED237BB170002AB46F /* ST.hpp */,
4BFDD7891F7F2DB4008579B9 /* Utility */,
4B6ED2EE208E2F8A0047B343 /* WOZ.cpp */,
4B6ED2EF208E2F8A0047B343 /* WOZ.hpp */,
);
path = Formats;
sourceTree = "<group>";
@ -4196,6 +4202,7 @@
4BBB70A5202011C2002FE009 /* MultiMediaTarget.cpp in Sources */,
4B8318BC22D3E588006DB630 /* DisplayMetrics.cpp in Sources */,
4B1B88BD202E3D3D00B67DFF /* MultiMachine.cpp in Sources */,
4BE0A3EF237BB170002AB46F /* ST.cpp in Sources */,
4B055A971FAE85BB0060FFFF /* ZX8081.cpp in Sources */,
4B055AAD1FAE85FD0060FFFF /* PCMTrack.cpp in Sources */,
4BD67DD1209BF27B00AB2146 /* Encoder.cpp in Sources */,
@ -4351,6 +4358,7 @@
4BD67DD0209BF27B00AB2146 /* Encoder.cpp in Sources */,
4BAE495920328897004BE78E /* ZX8081OptionsPanel.swift in Sources */,
4B89451A201967B4007DE474 /* ConfidenceSummary.cpp in Sources */,
4BE0A3EE237BB170002AB46F /* ST.cpp in Sources */,
4B54C0C51F8D91D90050900F /* Keyboard.cpp in Sources */,
4BEE149A227FC0EA00133682 /* IWM.cpp in Sources */,
4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */,

View File

@ -393,6 +393,7 @@
<key>CFBundleTypeExtensions</key>
<array>
<string>msa</string>
<string>st</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>floppy35.png</string>

View File

@ -22,10 +22,11 @@ void MFMSectorDump::set_geometry(int sectors_per_track, uint8_t sector_size, uin
}
std::shared_ptr<Track> MFMSectorDump::get_track_at_position(Track::Address address) {
uint8_t sectors[(128 << sector_size_)*sectors_per_track_];
if(address.head >= get_head_count()) return nullptr;
if(address.position.as_largest() >= get_maximum_head_position().as_largest()) return nullptr;
if(address.head > 1) return nullptr;
long file_offset = get_file_offset_for_position(address);
uint8_t sectors[(128 << sector_size_)*sectors_per_track_];
const long file_offset = get_file_offset_for_position(address);
{
std::lock_guard<std::mutex> lock_guard(file_.get_file_access_mutex());
@ -45,7 +46,7 @@ void MFMSectorDump::set_tracks(const std::map<Track::Address, std::shared_ptr<Tr
for(const auto &track : tracks) {
// Assumption here: sector IDs will run from 0.
decode_sectors(*track.second, parsed_track, first_sector_, first_sector_ + static_cast<uint8_t>(sectors_per_track_-1), sector_size_, is_double_density_);
long file_offset = get_file_offset_for_position(track.first);
const long file_offset = get_file_offset_for_position(track.first);
std::lock_guard<std::mutex> lock_guard(file_.get_file_access_mutex());
file_.ensure_is_at_least_length(file_offset);

View File

@ -25,7 +25,7 @@ SSD::SSD(const std::string &file_name) : MFMSectorDump(file_name) {
// this has two heads if the suffix is .dsd, one if it's .ssd
head_count_ = (tolower(file_name[file_name.size() - 3]) == 'd') ? 2 : 1;
track_count_ = int(file_.stats().st_size / (256 * 10));
track_count_ = int(file_.stats().st_size / (256 * 10 * head_count_));
if(track_count_ < 40) track_count_ = 40;
else if(track_count_ < 80) track_count_ = 80;

View File

@ -0,0 +1,42 @@
//
// ST.cpp
// Clock Signal
//
// Created by Thomas Harte on 12/11/2019.
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#include "ST.hpp"
namespace {
static const int sectors_per_track = 10;
static const int sector_size = 2;
}
using namespace Storage::Disk;
ST::ST(const std::string &file_name) : MFMSectorDump(file_name) {
// Very loose validation: the file needs to be a whole number of tracks,
// and not more than 160 of them.
const auto stats = file_.stats();
if(stats.st_size % 512*10) throw Error::InvalidFormat;
if(stats.st_size > 512*10*160) throw Error::InvalidFormat;
// Head count: 2 if there are more than 80 tracks. Otherwise 1.
head_count_ = (stats.st_size >= 512 * 10 * 80) ? 2 : 1;
track_count_ = std::max(80, int(stats.st_size / (512 * 10 * head_count_)));
set_geometry(sectors_per_track, sector_size, 1, true);
}
HeadPosition ST::get_maximum_head_position() {
return HeadPosition(track_count_);
}
int ST::get_head_count() {
return head_count_;
}
long ST::get_file_offset_for_position(Track::Address address) {
return (address.position.as_int() * head_count_ + address.head) * 512 * sectors_per_track;
}

View File

@ -0,0 +1,43 @@
//
// ST.hpp
// Clock Signal
//
// Created by Thomas Harte on 12/11/2019.
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef ST_hpp
#define ST_hpp
#include "MFMSectorDump.hpp"
namespace Storage {
namespace Disk {
/*!
Provides a @c Disk containing an ST disk image: a decoded sector dump of an Atari ST disk.
*/
class ST: public MFMSectorDump {
public:
/*!
Construct an @c ST containing content from the file with name @c file_name.
@throws Storage::FileHolder::Error::CantOpen if this file can't be opened.
@throws Error::InvalidFormat if the file doesn't appear to contain a .ST format image.
*/
ST(const std::string &file_name);
HeadPosition get_maximum_head_position() override;
int get_head_count() override;
private:
long get_file_offset_for_position(Track::Address address) override;
int head_count_;
int track_count_;
};
}
}
#endif /* ST_hpp */