From 6e4d3b8a7775b108ee4c66f26ed4b0bc4b79b05a Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 5 Aug 2017 11:44:53 -0400 Subject: [PATCH] Added enough logic to produce some sort of version of a completely unprotected DSK. So enough to start bootstrapping an FDC emulation, at least. --- Storage/Disk/Formats/CPCDSK.cpp | 84 +++++++++++++++++++++++++++++++++ Storage/Disk/Formats/CPCDSK.hpp | 8 ++++ 2 files changed, 92 insertions(+) diff --git a/Storage/Disk/Formats/CPCDSK.cpp b/Storage/Disk/Formats/CPCDSK.cpp index 2ce3f3dbe..92b024a84 100644 --- a/Storage/Disk/Formats/CPCDSK.cpp +++ b/Storage/Disk/Formats/CPCDSK.cpp @@ -8,6 +8,8 @@ #include "CPCDSK.hpp" +#include "../Encodings/MFM.hpp" + using namespace Storage::Disk; CPCDSK::CPCDSK(const char *file_name) : @@ -22,6 +24,14 @@ CPCDSK::CPCDSK(const char *file_name) : fseek(file_, 0x30, SEEK_SET); head_position_count_ = (unsigned int)fgetc(file_); head_count_ = (unsigned int)fgetc(file_); + + if(is_extended_) { + for(unsigned int c = 0; c < head_position_count_ * head_count_; c++) { + track_sizes_.push_back((size_t)(fgetc(file_) << 8)); + } + } else { + size_of_a_track_ = fgetc16le(); + } } unsigned int CPCDSK::get_head_position_count() { @@ -38,5 +48,79 @@ bool CPCDSK::get_is_read_only() { } std::shared_ptr CPCDSK::get_uncached_track_at_position(unsigned int head, unsigned int position) { + // Given that thesea are interleaved images, determine which track, chronologically, is being requested. + unsigned int chronological_track = (position * head_count_) + head; + + // All DSK images reserve 0x100 bytes for their headers. + long file_offset = 0x100; + if(is_extended_) { + // Tracks are a variable size in the original DSK file format; sum the lengths + // of all tracks prior to the interesting one to get a file offset. + unsigned int t = 0; + while(t < chronological_track && t < track_sizes_.size()) { + file_offset += track_sizes_[t]; + } + } else { + // Tracks are a fixed size in the original DSK file format. + file_offset += size_of_a_track_ * chronological_track; + } + + // Find the track, and skip the unused part of track information. + fseek(file_, file_offset + 16, SEEK_SET); + + // Grab the track information. + fseek(file_, 5, SEEK_CUR); // skip track number, side number, sector size — each is given per sector + int number_of_sectors = fgetc(file_); + uint8_t gap3_length = (uint8_t)fgetc(file_); + uint8_t filler_byte = (uint8_t)fgetc(file_); + + // Grab the sector information + struct SectorInfo { + uint8_t track; + uint8_t side; + uint8_t sector; + size_t length; + uint8_t status1; + uint8_t status2; + }; + std::vector sector_infos; + while(number_of_sectors--) { + SectorInfo new_sector; + + new_sector.track = (uint8_t)fgetc(file_); + new_sector.side = (uint8_t)fgetc(file_); + new_sector.sector = (uint8_t)fgetc(file_); + new_sector.length = (size_t)(128 << fgetc(file_)); + if(new_sector.length == 0x2000) new_sector.length = 0x1800; + new_sector.status1 = (uint8_t)fgetc(file_); + new_sector.status2 = (uint8_t)fgetc(file_); + fseek(file_, 2, SEEK_CUR); + + sector_infos.push_back(new_sector); + } + + // Get the sectors. + fseek(file_, file_offset + 0x100, SEEK_SET); + if(is_extended_) { + // TODO: everything about extended disk images + } else { + std::vector sectors; + for(auto §or_info : sector_infos) { + Storage::Encodings::MFM::Sector new_sector; + new_sector.track = sector_info.track; + new_sector.side = sector_info.side; + new_sector.sector = sector_info.sector; + new_sector.data.resize(sector_info.length); + fread(new_sector.data.data(), sizeof(uint8_t), sector_info.length, file_); + + // TODO: obey the status bytes, somehow (?) + + sectors.push_back(std::move(new_sector)); + } + + // TODO: supply gay 3 length and filler byte + if(sectors.size()) return Storage::Encodings::MFM::GetMFMTrackWithSectors(sectors); + } + return nullptr; } diff --git a/Storage/Disk/Formats/CPCDSK.hpp b/Storage/Disk/Formats/CPCDSK.hpp index 3b78a2ac5..0867dbb84 100644 --- a/Storage/Disk/Formats/CPCDSK.hpp +++ b/Storage/Disk/Formats/CPCDSK.hpp @@ -12,6 +12,8 @@ #include "../Disk.hpp" #include "../../FileHolder.hpp" +#include + namespace Storage { namespace Disk { @@ -43,6 +45,12 @@ class CPCDSK: public Disk, public Storage::FileHolder { unsigned int head_count_; unsigned int head_position_count_; bool is_extended_; + + // Used only for non-extended disks. + long size_of_a_track_; + + // Used only for extended disks. + std::vector track_sizes_; }; }