mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 01:31:42 +00:00
Adds output for modified CPC DSKs.
This commit is contained in:
parent
e384c50580
commit
5a3ca0e447
@ -18,6 +18,7 @@
|
||||
using namespace Storage::Disk;
|
||||
|
||||
CPCDSK::CPCDSK(const char *file_name) :
|
||||
file_name_(file_name),
|
||||
is_extended_(false) {
|
||||
FileHolder file(file_name);
|
||||
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);
|
||||
if(chronological_track >= tracks_.size()) {
|
||||
tracks_.resize(chronological_track+1);
|
||||
head_position_count_ = pair.first.position;
|
||||
}
|
||||
|
||||
// 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.
|
||||
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 §or: 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 §or: 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 §or: 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() {
|
||||
|
@ -64,6 +64,7 @@ class CPCDSK: public DiskImage {
|
||||
|
||||
std::vector<Sector> sectors;
|
||||
};
|
||||
std::string file_name_;
|
||||
std::vector<std::unique_ptr<Track>> tracks_;
|
||||
size_t index_for_track(::Storage::Disk::Track::Address address);
|
||||
|
||||
|
@ -92,6 +92,24 @@ uint8_t FileHolder::get8() {
|
||||
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> result(size);
|
||||
fread(result.data(), 1, size, file_);
|
||||
|
@ -62,21 +62,27 @@ class FileHolder final {
|
||||
and returning the two assembled in little endian order.
|
||||
*/
|
||||
uint16_t get16le();
|
||||
void put16le(uint16_t value);
|
||||
|
||||
/*!
|
||||
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.
|
||||
*/
|
||||
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();
|
||||
|
||||
|
||||
/*! 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);
|
||||
size_t read(uint8_t *buffer, size_t size);
|
||||
size_t write(const std::vector<uint8_t> &);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
|
||||
|
||||
void seek(long offset, int whence);
|
||||
long tell();
|
||||
void flush();
|
||||
|
Loading…
Reference in New Issue
Block a user