mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 16:31:31 +00:00
Adds read-only WOZ 2 support.
This commit is contained in:
parent
ab20a23f2b
commit
d065d6d98f
@ -18,11 +18,21 @@ using namespace Storage::Disk;
|
|||||||
WOZ::WOZ(const std::string &file_name) :
|
WOZ::WOZ(const std::string &file_name) :
|
||||||
file_(file_name) {
|
file_(file_name) {
|
||||||
|
|
||||||
const char signature[8] = {
|
constexpr const char signature1[8] = {
|
||||||
'W', 'O', 'Z', '1',
|
'W', 'O', 'Z', '1',
|
||||||
char(0xff), 0x0a, 0x0d, 0x0a
|
char(0xff), 0x0a, 0x0d, 0x0a
|
||||||
};
|
};
|
||||||
if(!file_.check_signature(signature, 8)) throw Error::InvalidFormat;
|
constexpr const char signature2[8] = {
|
||||||
|
'W', 'O', 'Z', '2',
|
||||||
|
char(0xff), 0x0a, 0x0d, 0x0a
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool isWoz1 = file_.check_signature(signature1, 8);
|
||||||
|
file_.seek(0, SEEK_SET);
|
||||||
|
const bool isWoz2 = file_.check_signature(signature2, 8);
|
||||||
|
|
||||||
|
if(!isWoz1 && !isWoz2) throw Error::InvalidFormat;
|
||||||
|
type_ = isWoz2 ? Type::WOZ2 : Type::WOZ1;
|
||||||
|
|
||||||
// Get the file's CRC32.
|
// Get the file's CRC32.
|
||||||
const uint32_t crc = file_.get32le();
|
const uint32_t crc = file_.get32le();
|
||||||
@ -52,13 +62,22 @@ WOZ::WOZ(const std::string &file_name) :
|
|||||||
switch(chunk_id) {
|
switch(chunk_id) {
|
||||||
case CK("INFO"): {
|
case CK("INFO"): {
|
||||||
const uint8_t version = file_.get8();
|
const uint8_t version = file_.get8();
|
||||||
if(version != 1) break;
|
if(version > 2) break;
|
||||||
is_3_5_disk_ = file_.get8() == 2;
|
is_3_5_disk_ = file_.get8() == 2;
|
||||||
is_read_only_ = file_.get8() == 1;
|
is_read_only_ = file_.get8() == 1;
|
||||||
/* Ignored:
|
/*
|
||||||
1 byte: Synchronized; 1 = Cross track sync was used during imaging.
|
Ignored:
|
||||||
1 byte: Cleaned; 1 = MC3470 fake bits have been removed.
|
1 byte: Synchronized; 1 = Cross track sync was used during imaging.
|
||||||
32 bytes: Cretor; a UTF-8 string.
|
1 byte: Cleaned; 1 = MC3470 fake bits have been removed.
|
||||||
|
32 bytes: Creator; a UTF-8 string.
|
||||||
|
|
||||||
|
And, if version 2, following the creator:
|
||||||
|
1 byte number of disk sides
|
||||||
|
1 byte boot sector format
|
||||||
|
1 byte optimal bit timing
|
||||||
|
2 bytes compatible hardware
|
||||||
|
2 bytes minimum required RAM
|
||||||
|
2 bytes largest track
|
||||||
*/
|
*/
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -99,11 +118,15 @@ long WOZ::file_offset(Track::Address address) {
|
|||||||
if(track_map_[table_position] == 0xff) return NoSuchTrack;
|
if(track_map_[table_position] == 0xff) return NoSuchTrack;
|
||||||
|
|
||||||
// Seek to the real track.
|
// Seek to the real track.
|
||||||
return tracks_offset_ + track_map_[table_position] * 6656;
|
switch(type_) {
|
||||||
|
case Type::WOZ1: return tracks_offset_ + track_map_[table_position] * 6656;
|
||||||
|
default:
|
||||||
|
case Type::WOZ2: return tracks_offset_ + track_map_[table_position] * 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Track> WOZ::get_track_at_position(Track::Address address) {
|
std::shared_ptr<Track> WOZ::get_track_at_position(Track::Address address) {
|
||||||
long offset = file_offset(address);
|
const long offset = file_offset(address);
|
||||||
if(offset == NoSuchTrack) return nullptr;
|
if(offset == NoSuchTrack) return nullptr;
|
||||||
|
|
||||||
// Seek to the real track.
|
// Seek to the real track.
|
||||||
@ -113,18 +136,34 @@ std::shared_ptr<Track> WOZ::get_track_at_position(Track::Address address) {
|
|||||||
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
||||||
file_.seek(offset, SEEK_SET);
|
file_.seek(offset, SEEK_SET);
|
||||||
|
|
||||||
// In WOZ a track is up to 6646 bytes of data, followed by a two-byte record of the
|
switch(type_) {
|
||||||
// number of bytes that actually had data in them, then a two-byte count of the number
|
case Type::WOZ1:
|
||||||
// of bits that were used. Other information follows but is not intended for emulation.
|
// In WOZ 1, a track is up to 6646 bytes of data, followed by a two-byte record of the
|
||||||
track_contents = file_.read(6646);
|
// number of bytes that actually had data in them, then a two-byte count of the number
|
||||||
file_.seek(2, SEEK_CUR);
|
// of bits that were used. Other information follows but is not intended for emulation.
|
||||||
number_of_bits = std::min(file_.get16le(), uint16_t(6646*8));
|
track_contents = file_.read(6646);
|
||||||
|
file_.seek(2, SEEK_CUR);
|
||||||
|
number_of_bits = std::min(file_.get16le(), uint16_t(6646*8));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type::WOZ2: {
|
||||||
|
// In WOZ 2 an extra level of indirection allows for variable track sizes.
|
||||||
|
const uint16_t starting_block = file_.get16le();
|
||||||
|
file_.seek(2, SEEK_CUR); // Skip the block count; the amount of data to read is implied by the number of bits.
|
||||||
|
number_of_bits = file_.get32le();
|
||||||
|
|
||||||
|
file_.seek(starting_block * 512, SEEK_SET);
|
||||||
|
track_contents = file_.read((number_of_bits + 7) >> 3);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<PCMTrack>(PCMSegment(number_of_bits, track_contents));
|
return std::make_shared<PCMTrack>(PCMSegment(number_of_bits, track_contents));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WOZ::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) {
|
void WOZ::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) {
|
||||||
|
if(type_ == Type::WOZ2) return;
|
||||||
|
|
||||||
for(const auto &pair: tracks) {
|
for(const auto &pair: tracks) {
|
||||||
// Decode the track and store, patching into the post_crc_contents_.
|
// Decode the track and store, patching into the post_crc_contents_.
|
||||||
auto segment = Storage::Disk::track_serialisation(*pair.second, Storage::Time(1, 50000));
|
auto segment = Storage::Disk::track_serialisation(*pair.second, Storage::Time(1, 50000));
|
||||||
@ -155,5 +194,5 @@ void WOZ::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tra
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WOZ::get_is_read_only() {
|
bool WOZ::get_is_read_only() {
|
||||||
return file_.get_is_known_read_only();
|
return file_.get_is_known_read_only() || is_read_only_ || type_ == Type::WOZ2; // WOZ 2 disks are currently read only.
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,9 @@ class WOZ: public DiskImage {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Storage::FileHolder file_;
|
Storage::FileHolder file_;
|
||||||
|
enum class Type {
|
||||||
|
WOZ1, WOZ2
|
||||||
|
} type_ = Type::WOZ1;
|
||||||
bool is_read_only_ = false;
|
bool is_read_only_ = false;
|
||||||
bool is_3_5_disk_ = false;
|
bool is_3_5_disk_ = false;
|
||||||
uint8_t track_map_[160];
|
uint8_t track_map_[160];
|
||||||
|
Loading…
Reference in New Issue
Block a user