1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-29 12:50:28 +00:00

Adds output for modified CPC DSKs.

This commit is contained in:
Thomas Harte 2017-11-03 21:10:22 -04:00
parent e384c50580
commit 5a3ca0e447
4 changed files with 137 additions and 3 deletions

View File

@ -18,6 +18,7 @@
using namespace Storage::Disk; using namespace Storage::Disk;
CPCDSK::CPCDSK(const char *file_name) : CPCDSK::CPCDSK(const char *file_name) :
file_name_(file_name),
is_extended_(false) { is_extended_(false) {
FileHolder file(file_name); FileHolder file(file_name);
is_read_only_ = file.get_is_known_read_only(); is_read_only_ = file.get_is_known_read_only();
@ -230,6 +231,7 @@ void CPCDSK::set_tracks(const std::map<::Storage::Disk::Track::Address, std::sha
size_t chronological_track = index_for_track(pair.first); size_t chronological_track = index_for_track(pair.first);
if(chronological_track >= tracks_.size()) { if(chronological_track >= tracks_.size()) {
tracks_.resize(chronological_track+1); tracks_.resize(chronological_track+1);
head_position_count_ = pair.first.position;
} }
// Get the track, or create it if necessary. // Get the track, or create it if necessary.
@ -263,6 +265,113 @@ void CPCDSK::set_tracks(const std::map<::Storage::Disk::Track::Address, std::sha
} }
// Rewrite the entire disk image, in extended form. // Rewrite the entire disk image, in extended form.
Storage::FileHolder output(file_name_, Storage::FileHolder::FileMode::Rewrite);
output.write(reinterpret_cast<const uint8_t *>("EXTENDED CPC DSK File\r\nDisk-Info\r\n"), 34);
output.write(reinterpret_cast<const uint8_t *>("Clock Signal "), 14);
output.put8(static_cast<uint8_t>(head_position_count_));
output.put8(static_cast<uint8_t>(head_count_));
output.putn(2, 0);
// Output size table.
for(size_t index = 0; index < static_cast<size_t>(head_position_count_ * head_count_); ++index) {
if(index >= tracks_.size()) {
output.put8(0);
continue;
}
Track *track = tracks_[index].get();
if(!track) {
output.put8(0);
continue;
}
// Calculate size of track.
size_t track_size = 256;
for(auto &sector: track->sectors) {
for(auto &sample: sector.samples) {
track_size += sample.size();
}
}
// Round upward and output.
track_size += (256 - (track_size & 255)) & 255;
output.put8(static_cast<uint8_t>(track_size >> 8));
}
// Advance to offset 256.
output.putn(static_cast<size_t>(256 - output.tell()), 0);
// Output each track.
for(size_t index = 0; index < static_cast<size_t>(head_position_count_ * head_count_); ++index) {
if(index >= tracks_.size()) continue;
Track *track = tracks_[index].get();
if(!track) continue;
// Output track header.
output.write(reinterpret_cast<const uint8_t *>("Track-Info\r\n"), 13);
output.putn(3, 0);
output.put8(track->track);
output.put8(track->side);
switch (track->data_rate) {
default:
output.put8(0);
break;
case Track::DataRate::SingleOrDoubleDensity:
output.put8(1);
break;
case Track::DataRate::HighDensity:
output.put8(2);
break;
case Track::DataRate::ExtendedDensity:
output.put8(3);
break;
}
switch (track->data_encoding) {
default:
output.put8(0);
break;
case Track::DataEncoding::FM:
output.put8(1);
break;
case Track::DataEncoding::MFM:
output.put8(2);
break;
}
output.put8(track->sector_length);
output.put8(static_cast<uint8_t>(track->sectors.size()));
output.put8(track->gap3_length);
output.put8(track->filler_byte);
// Output sector information list.
for(auto &sector: track->sectors) {
output.put8(sector.address.track);
output.put8(sector.address.side);
output.put8(sector.address.sector);
output.put8(sector.size);
output.put8(sector.fdc_status1);
output.put8(sector.fdc_status2);
size_t data_size = 0;
for(auto &sample: sector.samples) {
data_size += sample.size();
}
output.put16le(static_cast<uint16_t>(data_size));
}
// Move to next 256-byte boundary.
long distance = (256 - output.tell()&255)&255;
output.putn(static_cast<size_t>(distance), 0);
// Output sector contents.
for(auto &sector: track->sectors) {
for(auto &sample: sector.samples) {
output.write(sample);
}
}
// Move to next 256-byte boundary.
distance = (256 - output.tell()&255)&255;
output.putn(static_cast<size_t>(distance), 0);
}
} }
bool CPCDSK::get_is_read_only() { bool CPCDSK::get_is_read_only() {

View File

@ -64,6 +64,7 @@ class CPCDSK: public DiskImage {
std::vector<Sector> sectors; std::vector<Sector> sectors;
}; };
std::string file_name_;
std::vector<std::unique_ptr<Track>> tracks_; std::vector<std::unique_ptr<Track>> tracks_;
size_t index_for_track(::Storage::Disk::Track::Address address); size_t index_for_track(::Storage::Disk::Track::Address address);

View File

@ -92,6 +92,24 @@ uint8_t FileHolder::get8() {
return static_cast<uint8_t>(fgetc(file_)); return static_cast<uint8_t>(fgetc(file_));
} }
void FileHolder::put16be(uint16_t value) {
fputc(value >> 8, file_);
fputc(value, file_);
}
void FileHolder::put16le(uint16_t value) {
fputc(value, file_);
fputc(value >> 8, file_);
}
void FileHolder::put8(uint8_t value) {
fputc(value, file_);
}
void FileHolder::putn(size_t repeats, uint8_t value) {
while(repeats--) put8(value);
}
std::vector<uint8_t> FileHolder::read(size_t size) { std::vector<uint8_t> FileHolder::read(size_t size) {
std::vector<uint8_t> result(size); std::vector<uint8_t> result(size);
fread(result.data(), 1, size, file_); fread(result.data(), 1, size, file_);

View File

@ -62,16 +62,22 @@ class FileHolder final {
and returning the two assembled in little endian order. and returning the two assembled in little endian order.
*/ */
uint16_t get16le(); uint16_t get16le();
void put16le(uint16_t value);
/*! /*!
Performs @c get8 two times on @c file, casting each result to a @c uint32_t Performs @c get8 two times on @c file, casting each result to a @c uint32_t
and returning the two assembled in big endian order. and returning the two assembled in big endian order.
*/ */
uint16_t get16be(); uint16_t get16be();
void put16be(uint16_t value);
/*! Reads a single byte from @c file */ /*! Reads a single byte from @c file. */
uint8_t get8(); uint8_t get8();
/*! Writes a single byte from @c file. */
void put8(uint8_t value);
void putn(size_t repeats, uint8_t value);
std::vector<uint8_t> read(size_t size); std::vector<uint8_t> read(size_t size);
size_t read(uint8_t *buffer, size_t size); size_t read(uint8_t *buffer, size_t size);
size_t write(const std::vector<uint8_t> &); size_t write(const std::vector<uint8_t> &);