mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +00:00
Adds provisional support for WOZ files.
This commit is contained in:
parent
6592745e53
commit
d447e81abd
@ -39,6 +39,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/WOZ.hpp"
|
||||
|
||||
// Tapes
|
||||
#include "../../Storage/Tape/Formats/CAS.hpp"
|
||||
@ -129,6 +130,7 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
|
||||
Format("tsx", result.tapes, Tape::TZX, TargetPlatform::MSX) // TSX
|
||||
Format("tzx", result.tapes, Tape::TZX, TargetPlatform::ZX8081) // TZX
|
||||
Format("uef", result.tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape)
|
||||
Format("woz", result.disks, Disk::DiskImageHolder<Storage::Disk::WOZ>, TargetPlatform::AppleII) // WOZ
|
||||
|
||||
#undef Format
|
||||
#undef Insert
|
||||
|
@ -222,6 +222,8 @@
|
||||
4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */; };
|
||||
4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; };
|
||||
4B6A4C991F58F09E00E3F787 /* 6502Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */; };
|
||||
4B6ED2F0208E2F8A0047B343 /* WOZ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6ED2EE208E2F8A0047B343 /* WOZ.cpp */; };
|
||||
4B6ED2F1208E2F8A0047B343 /* WOZ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6ED2EE208E2F8A0047B343 /* WOZ.cpp */; };
|
||||
4B7136861F78724F008B8ED9 /* Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136841F78724F008B8ED9 /* Encoder.cpp */; };
|
||||
4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136871F78725F008B8ED9 /* Shifter.cpp */; };
|
||||
4B71368E1F788112008B8ED9 /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368C1F788112008B8ED9 /* Parser.cpp */; };
|
||||
@ -889,6 +891,8 @@
|
||||
4B6A4C911F58F09E00E3F787 /* 6502AllRAM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502AllRAM.cpp; sourceTree = "<group>"; };
|
||||
4B6A4C921F58F09E00E3F787 /* 6502AllRAM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6502AllRAM.hpp; sourceTree = "<group>"; };
|
||||
4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502Base.cpp; sourceTree = "<group>"; };
|
||||
4B6ED2EE208E2F8A0047B343 /* WOZ.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WOZ.cpp; sourceTree = "<group>"; };
|
||||
4B6ED2EF208E2F8A0047B343 /* WOZ.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = WOZ.hpp; sourceTree = "<group>"; };
|
||||
4B7041271F92C26900735E45 /* JoystickMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = JoystickMachine.hpp; sourceTree = "<group>"; };
|
||||
4B70412A1F92C2A700735E45 /* Joystick.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Joystick.hpp; sourceTree = "<group>"; };
|
||||
4B70EF6A1FFDCDF400A3494E /* ROMSlotHandler.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = ROMSlotHandler.hpp; path = MSX/ROMSlotHandler.hpp; sourceTree = "<group>"; };
|
||||
@ -1879,6 +1883,8 @@
|
||||
4B4518981F75FD1B00926311 /* OricMFMDSK.hpp */,
|
||||
4B45189A1F75FD1B00926311 /* SSD.hpp */,
|
||||
4BFDD7891F7F2DB4008579B9 /* Utility */,
|
||||
4B6ED2EE208E2F8A0047B343 /* WOZ.cpp */,
|
||||
4B6ED2EF208E2F8A0047B343 /* WOZ.hpp */,
|
||||
);
|
||||
path = Formats;
|
||||
sourceTree = "<group>";
|
||||
@ -3536,6 +3542,7 @@
|
||||
4BB0A65E204500A900FB3688 /* StaticAnalyser.cpp in Sources */,
|
||||
4B055AC11FAE98DC0060FFFF /* MachineForTarget.cpp in Sources */,
|
||||
4BBB70A9202014E2002FE009 /* MultiCRTMachine.cpp in Sources */,
|
||||
4B6ED2F1208E2F8A0047B343 /* WOZ.cpp in Sources */,
|
||||
4B055AD81FAE9B180060FFFF /* Video.cpp in Sources */,
|
||||
4B89452F201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
4B894531201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
@ -3808,6 +3815,7 @@
|
||||
4B894526201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */,
|
||||
4B8805FB1DCFF807003085B1 /* Oric.cpp in Sources */,
|
||||
4B6ED2F0208E2F8A0047B343 /* WOZ.cpp in Sources */,
|
||||
4BFE7B871FC39BF100160B38 /* StandardOptions.cpp in Sources */,
|
||||
4B15A9FC208249BB005E6C8D /* StaticAnalyser.cpp in Sources */,
|
||||
4B5FADC01DE3BF2B00AEC565 /* Microdisc.cpp in Sources */,
|
||||
|
@ -68,7 +68,7 @@
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Release"
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
enableASanStackUseAfterReturn = "YES"
|
||||
|
@ -397,6 +397,7 @@
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>nib</string>
|
||||
<string>woz</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>floppy525</string>
|
||||
|
100
Storage/Disk/DiskImage/Formats/WOZ.cpp
Normal file
100
Storage/Disk/DiskImage/Formats/WOZ.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
//
|
||||
// WOZ.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 23/04/2018.
|
||||
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "WOZ.hpp"
|
||||
|
||||
#include "../../Track/PCMTrack.hpp"
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
WOZ::WOZ(const std::string &file_name) :
|
||||
file_(file_name) {
|
||||
|
||||
const char signature[8] = {
|
||||
'W', 'O', 'Z', '1',
|
||||
static_cast<char>(0xff), 0x0a, 0x0d, 0x0a
|
||||
};
|
||||
if(!file_.check_signature(signature, 8)) throw ErrorNotWOZ;
|
||||
|
||||
// TODO: check CRC32, instead of skipping it.
|
||||
file_.seek(4, SEEK_CUR);
|
||||
|
||||
// Parse all chunks up front.
|
||||
while(true) {
|
||||
const uint32_t chunk_id = file_.get32le();
|
||||
const uint32_t chunk_size = file_.get32le();
|
||||
if(file_.eof()) break;
|
||||
|
||||
long end_of_chunk = file_.tell() + static_cast<long>(chunk_size);
|
||||
|
||||
#define CK(str) (str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24))
|
||||
switch(chunk_id) {
|
||||
case CK("INFO"): {
|
||||
const uint8_t version = file_.get8();
|
||||
if(version != 1) break;
|
||||
is_3_5_disk_ = file_.get8() == 2;
|
||||
is_read_only_ = file_.get8() == 1;
|
||||
/* Ignored:
|
||||
1 byte: Synchronized; 1 = Cross track sync was used during imaging.
|
||||
1 byte: Cleaned; 1 = MC3470 fake bits have been removed.
|
||||
32 bytes: Cretor; a UTF-8 string.
|
||||
*/
|
||||
} break;
|
||||
|
||||
case CK("TMAP"): {
|
||||
file_.read(track_map_, 160);
|
||||
} break;
|
||||
|
||||
case CK("TRKS"): {
|
||||
tracks_offset_ = file_.tell();
|
||||
} break;
|
||||
|
||||
// TODO: parse META chunks.
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
file_.seek(end_of_chunk, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
int WOZ::get_head_position_count() {
|
||||
// TODO: deal with the elephant in the room of non-integral track coordinates.
|
||||
return is_3_5_disk_ ? 80 : 160;
|
||||
}
|
||||
|
||||
int WOZ::get_head_count() {
|
||||
return is_3_5_disk_ ? 2 : 1;
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> WOZ::get_track_at_position(Track::Address address) {
|
||||
// Out-of-bounds => no track.
|
||||
if(address.head >= get_head_count()) return nullptr;
|
||||
if(address.position >= get_head_position_count()) return nullptr;
|
||||
|
||||
// Calculate table position; if this track is defined to be unformatted, return no track.
|
||||
const int table_position = address.head * get_head_position_count() + address.position;
|
||||
if(track_map_[table_position] == 0xff) return nullptr;
|
||||
|
||||
// Seek to the real track.
|
||||
file_.seek(tracks_offset_ + track_map_[table_position] * 6656, SEEK_SET);
|
||||
|
||||
PCMSegment track_contents;
|
||||
track_contents.data = file_.read(6646);
|
||||
track_contents.data.resize(file_.get16le());
|
||||
track_contents.number_of_bits = file_.get16le();
|
||||
|
||||
const uint16_t splice_point = file_.get16le();
|
||||
if(splice_point != 0xffff) {
|
||||
// TODO: expand track from splice_point?
|
||||
}
|
||||
|
||||
return std::shared_ptr<PCMTrack>(new PCMTrack(track_contents));
|
||||
}
|
46
Storage/Disk/DiskImage/Formats/WOZ.hpp
Normal file
46
Storage/Disk/DiskImage/Formats/WOZ.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// WOZ.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 23/04/2018.
|
||||
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef WOZ_hpp
|
||||
#define WOZ_hpp
|
||||
|
||||
#include "../DiskImage.hpp"
|
||||
#include "../../../FileHolder.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
/*!
|
||||
Provides a @c DiskImage containing a WOZ — a bit stream representation of a floppy.
|
||||
*/
|
||||
class WOZ: public DiskImage {
|
||||
public:
|
||||
WOZ(const std::string &file_name);
|
||||
|
||||
enum {
|
||||
ErrorNotWOZ
|
||||
};
|
||||
|
||||
int get_head_position_count() override;
|
||||
int get_head_count() override;
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address address) override;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
bool is_read_only_ = false;
|
||||
bool is_3_5_disk_ = false;
|
||||
uint8_t track_map_[160];
|
||||
long tracks_offset_ = 0;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WOZ_hpp */
|
Loading…
Reference in New Issue
Block a user