diff --git a/arch/victor9k/encoder.cc b/arch/victor9k/encoder.cc index 17c6fe68..46d177fa 100644 --- a/arch/victor9k/encoder.cc +++ b/arch/victor9k/encoder.cc @@ -47,8 +47,9 @@ public: Victor9kEncoderProto::TrackdataProto trackdata; getTrackFormat(trackdata, physicalTrack, physicalSide); - for (int sectorId : trackdata.sectors().sector()) + for (int i = 0; i < trackdata.sector_range().sector_count(); i++) { + int sectorId = trackdata.sector_range().start_sector() + i; const auto& sector = image.get(physicalTrack, physicalSide, sectorId); if (sector) sectors.push_back(sector); @@ -63,8 +64,9 @@ public: Victor9kEncoderProto::TrackdataProto trackdata; getTrackFormat(trackdata, physicalTrack, physicalSide); - std::vector bits(trackdata.bits_per_revolution()); - unsigned clockRateUs = 166666.0 / trackdata.bits_per_revolution(); + unsigned bitsPerRevolution = trackdata.original_data_rate_khz() * trackdata.original_period_ms(); + std::vector bits(bitsPerRevolution); + double clockRateUs = 166666.0 / bitsPerRevolution; unsigned cursor = 0; fillBitmapTo(bits, cursor, trackdata.post_index_gap_us() / clockRateUs, { true, false }); diff --git a/arch/victor9k/victor9k.proto b/arch/victor9k/victor9k.proto index b44c1934..fb21faf3 100644 --- a/arch/victor9k/victor9k.proto +++ b/arch/victor9k/victor9k.proto @@ -6,18 +6,20 @@ message Victor9kDecoderProto {} message Victor9kEncoderProto { message TrackdataProto { - message SectorsProto { - repeated int32 sector = 1 [(help) = "write these sectors (in order) on each track"]; + message SectorRangeProto { + optional int32 start_sector = 1 [(help) = "first sector ID on track"]; + optional int32 sector_count = 2 [(help) = "number of sectors on track"]; } - optional int32 min_cylinder = 1 [(help) = "minimum cylinder this format applies to"]; - optional int32 max_cylinder = 2 [(help) = "maximum cylinder this format applies to"]; - optional int32 head = 3 [(help) = "which head this format applies to"]; + optional int32 min_cylinder = 1 [(help) = "minimum cylinder this format applies to"]; + optional int32 max_cylinder = 2 [(help) = "maximum cylinder this format applies to"]; + optional int32 head = 3 [(help) = "which head this format applies to"]; - optional int32 bits_per_revolution = 4 [(help) = "number of bits on this cylinder"]; - optional double post_index_gap_us = 5 [(help) = "size of post-index gap"]; + optional double original_period_ms = 4 [(help) = "original rotational period of this cylinder"]; + optional double original_data_rate_khz = 5 [(help) = "original data rate of this cylinder"]; + optional double post_index_gap_us = 6 [(help) = "size of post-index gap"]; - optional SectorsProto sectors = 6 [(help) = "write these sectors (in order) on each track"]; + optional SectorRangeProto sector_range = 7 [(help) = "write these sectors on each track"]; } repeated TrackdataProto trackdata = 1; diff --git a/doc/disk-victor9k.md b/doc/disk-victor9k.md index 21f019e1..f8721a09 100644 --- a/doc/disk-victor9k.md +++ b/doc/disk-victor9k.md @@ -6,7 +6,25 @@ which used a disk format very reminiscent of the Commodore format; not a coincidence, as Chuck Peddle designed them both. They're 80-track, 512-byte sector GCR disks, with a variable-speed drive and a varying number of sectors per track --- from 19 to 12. Disks can be double-sided, meaning that they can -store 1224kB per disk, which was almost unheard of back then. +store 1224kB per disk, which was almost unheard of back then. Because the way +that the tracks on head 1 are offset from head 0 (this happens with all disks), +the speed zone allocation on head 1 differ from head 0... + +| Zone | Head 0 tracks | Head 1 tracks | Sectors | Original period (ms) | +|:----:|:-------------:|:-------------:|:-------:|:--------------------:| +| 0 | 0-3 | | 19 | 237.9 | +| 1 | 4-15 | 0-7 | 18 | 224.5 | +| 2 | 16-26 | 8-18 | 17 | 212.2 | +| 3 | 27-37 | 19-29 | 16 | 199.9 | +| 4 | 38-48 | 30-40 | 15 | 187.6 | +| 5 | 49-59 | 41-51 | 14 | 175.3 | +| 6 | 60-70 | 52-62 | 13 | 163.0 | +| 7 | 71-79 | 63-74 | 12 | 149.6 | +| 8 | | 75-79 | 11 | 144.0 | + +(The Original Period column is the original rotation rate. When used in +FluxEngine, the disk always spins at 360 rpm, which corresponds to a rotational +period of 166 ms.) FluxEngine reads these. diff --git a/src/formats/victor9k.textpb b/src/formats/victor9k.textpb index b77f4bfc..42841486 100644 --- a/src/formats/victor9k.textpb +++ b/src/formats/victor9k.textpb @@ -1,5 +1,80 @@ comment: 'Victor 9000 / Sirius One 1224kB SSHD GCR variable sector (ro)' +image_reader { + filename: "victor9k.img" + img { + tracks: 80 + sides: 1 + trackdata { + sector_size: 512 + } + trackdata { + track: 0 + up_to_track: 3 + sector_range { + start_sector: 1 + sector_count: 19 + } + } + trackdata { + track: 4 + up_to_track: 15 + sector_range { + start_sector: 1 + sector_count: 18 + } + } + trackdata { + track: 16 + up_to_track: 26 + sector_range { + start_sector: 1 + sector_count: 17 + } + } + trackdata { + track: 27 + up_to_track: 37 + sector_range { + start_sector: 1 + sector_count: 16 + } + } + trackdata { + track: 38 + up_to_track: 47 + sector_range { + start_sector: 1 + sector_count: 15 + } + } + trackdata { + track: 48 + up_to_track: 59 + sector_range { + start_sector: 1 + sector_count: 14 + } + } + trackdata { + track: 60 + up_to_track: 70 + sector_range { + start_sector: 1 + sector_count: 13 + } + } + trackdata { + track: 71 + up_to_track: 79 + sector_range { + start_sector: 1 + sector_count: 12 + } + } + } +} + image_writer { filename: "victor9k.img" img { @@ -75,11 +150,98 @@ image_writer { } } -decoder { +encoder { victor9k { + trackdata { + original_data_rate_khz: 500 + } + trackdata { + head: 0 + min_cylinder: 0 + max_cylinder: 3 + original_period_ms: 237.9 + sector_range { + start_sector: 1 + sector_count: 19 + } + } + trackdata { + head: 0 + min_cylinder: 4 + max_cylinder: 15 + original_period_ms: 224.5 + sector_range { + start_sector: 1 + sector_count: 18 + } + } + trackdata { + head: 0 + min_cylinder: 16 + max_cylinder: 26 + original_period_ms: 212.2 + sector_range { + start_sector: 1 + sector_count: 17 + } + } + trackdata { + head: 0 + min_cylinder: 27 + max_cylinder: 37 + original_period_ms: 199.9 + sector_range { + start_sector: 1 + sector_count: 16 + } + } + trackdata { + head: 0 + min_cylinder: 38 + max_cylinder: 48 + original_period_ms: 187.6 + sector_range { + start_sector: 1 + sector_count: 15 + } + } + trackdata { + head: 0 + min_cylinder: 49 + max_cylinder: 59 + original_period_ms: 175.3 + sector_range { + start_sector: 1 + sector_count: 14 + } + } + trackdata { + head: 0 + min_cylinder: 60 + max_cylinder: 70 + original_period_ms: 163.0 + sector_range { + start_sector: 1 + sector_count: 13 + } + } + trackdata { + head: 0 + min_cylinder: 71 + max_cylinder: 79 + original_period_ms: 149.6 + sector_range { + start_sector: 1 + sector_count: 12 + } + } } } +decoder { + victor9k {} +} + cylinders { start: 0 end: 79