diff --git a/Makefile b/Makefile index 38528f67c..4ea0328c5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PACKAGES = zlib sqlite3 libusb-1.0 protobuf -export CFLAGS = -x c++ --std=c++2a -ffunction-sections -fdata-sections +export CFLAGS = -x c++ --std=c++14 -ffunction-sections -fdata-sections export LDFLAGS = -pthread export COPTFLAGS = -Os diff --git a/README.md b/README.md index d1aedb4c3..1f2d59e0e 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,7 @@ people who've had it work). | [Brother 120kB](doc/disk-brother.md) | 🦄 | 🦖 | | | [Brother 240kB](doc/disk-brother.md) | 🦄 | 🦄 | | | [Brother FB-100](doc/disk-fb100.md) | 🦖 | | Tandy Model 100, Husky Hunter, knitting machines | +| [Kaypro II](doc/disk-ibm.md) | 🦄 | 🦄 | | | [Macintosh 800kB](doc/disk-macintosh.md) | 🦄 | 🦄 | and probably the 400kB too | | [TRS-80](doc/disk-trs80.md) | 🦖 | 🦖* | a minor variation of the IBM scheme | {: .datatable } diff --git a/arch/ibm/encoder.cc b/arch/ibm/encoder.cc index 153757370..3308ae76b 100644 --- a/arch/ibm/encoder.cc +++ b/arch/ibm/encoder.cc @@ -144,7 +144,7 @@ class IbmEncoder : public AbstractEncoder if (!trackdata.use_fm()) clockRateUs /= 2.0; int bitsPerRevolution = (trackdata.track_length_ms() * 1000.0) / clockRateUs; - _bits.resize(bitsPerRevolution); + _bits.resize(bitsPerRevolution*2); _cursor = 0; uint8_t idamUnencoded = decodeUint16(trackdata.idam_byte()); @@ -261,12 +261,15 @@ class IbmEncoder : public AbstractEncoder } } - if (_cursor >= _bits.size()) - Error() << "track data overrun"; + if (_cursor >= bitsPerRevolution) + Error() << fmt::format("track data overrun by {} bits ({:.3} ms)", + _cursor - bitsPerRevolution, + (_cursor - bitsPerRevolution) / (clockRateUs*1000.0)); while (_cursor < _bits.size()) writeFillerBytes(1, gapFill); std::unique_ptr fluxmap(new Fluxmap); + _bits.resize(bitsPerRevolution); fluxmap->appendBits(_bits, clockRateUs*1e3); return fluxmap; } diff --git a/doc/disk-ibm.md b/doc/disk-ibm.md index a74df292f..00c6fb3c9 100644 --- a/doc/disk-ibm.md +++ b/doc/disk-ibm.md @@ -14,6 +14,7 @@ metadata. Systems which use IBM scheme disks include but are not limited to: - the TRS-80 - late era Commodore machines (the 1571 and so on) - most CP/M machines + - the Kaypro II - etc FluxEngine supports reading these. However, some variants are more peculiar diff --git a/lib/imagereader/diskcopyimagereader.cc b/lib/imagereader/diskcopyimagereader.cc index 546ba3874..62a55c69d 100644 --- a/lib/imagereader/diskcopyimagereader.cc +++ b/lib/imagereader/diskcopyimagereader.cc @@ -115,13 +115,13 @@ class DiskCopyImageReader : public ImageReader } } - image.setGeometry({ - .numTracks = numCylinders, - .numSides = numHeads, - .numSectors = 12, - .sectorSize = 512 + 12, - .irregular = true - }); + Geometry g; + g.numTracks = numCylinders; + g.numSides = numHeads; + g.numSectors = 12; + g.sectorSize = 512 + 12; + g.irregular = true; + image.setGeometry(g); return image; } }; diff --git a/lib/imagereader/imdimagereader.cc b/lib/imagereader/imdimagereader.cc index d45485a3b..7c74420ba 100644 --- a/lib/imagereader/imdimagereader.cc +++ b/lib/imagereader/imdimagereader.cc @@ -259,12 +259,12 @@ class IMDImageReader : public ImageReader } //Write format detected in IMD image to screen to help user set the right write parameters - image.setGeometry({ - .numTracks = header.track, - .numSides = header.Head + 1U, - .numSectors = header.numSectors, - .sectorSize = sectorSize - }); + Geometry g; + g.numTracks = header.track; + g.numSides = header.Head + 1U; + g.numSectors = header.numSectors; + g.sectorSize = sectorSize; + image.setGeometry(g); size_t headSize = header.numSectors * sectorSize; size_t trackSize = headSize * (header.Head + 1); diff --git a/lib/imagereader/nsiimagereader.cc b/lib/imagereader/nsiimagereader.cc index e327ac325..c7e024c77 100644 --- a/lib/imagereader/nsiimagereader.cc +++ b/lib/imagereader/nsiimagereader.cc @@ -97,12 +97,12 @@ class NsiImageReader : public ImageReader } } - image.setGeometry({ - .numTracks = numCylinders, - .numSides = numHeads, - .numSectors = numSectors, - .sectorSize = sectorSize - }); + Geometry g; + g.numTracks = numCylinders; + g.numSides = numHeads; + g.numSectors = numSectors; + g.sectorSize = sectorSize; + image.setGeometry(g); return image; } }; diff --git a/lib/usb/fluxengineusb.cc b/lib/usb/fluxengineusb.cc index af9a570ed..4225c80d6 100644 --- a/lib/usb/fluxengineusb.cc +++ b/lib/usb/fluxengineusb.cc @@ -120,7 +120,9 @@ class FluxEngineUsb : public USB public: int getVersion() { - struct any_frame f = { .f = {.type = F_FRAME_GET_VERSION_CMD, .size = sizeof(f)} }; + struct any_frame f; + f.f.type = F_FRAME_GET_VERSION_CMD; + f.f.size = sizeof(f); usb_cmd_send(&f, f.f.size); auto r = await_reply(F_FRAME_GET_VERSION_REPLY); return r->version; @@ -128,29 +130,29 @@ class FluxEngineUsb : public USB void seek(int track) { - struct seek_frame f = { - .f = { .type = F_FRAME_SEEK_CMD, .size = sizeof(f) }, - .track = (uint8_t) track - }; + struct seek_frame f; + f.f.type = F_FRAME_SEEK_CMD; + f.f.size = sizeof(f); + f.track = (uint8_t) track; usb_cmd_send(&f, f.f.size); await_reply(F_FRAME_SEEK_REPLY); } void recalibrate() { - struct any_frame f = { - .f = { .type = F_FRAME_RECALIBRATE_CMD, .size = sizeof(f) }, - }; + struct any_frame f; + f.f.type = F_FRAME_RECALIBRATE_CMD; + f.f.size = sizeof(f); usb_cmd_send(&f, f.f.size); await_reply(F_FRAME_RECALIBRATE_REPLY); } nanoseconds_t getRotationalPeriod(int hardSectorCount) { - struct measurespeed_frame f = { - .f = {.type = F_FRAME_MEASURE_SPEED_CMD, .size = sizeof(f)}, - .hard_sector_count = (uint8_t) hardSectorCount, - }; + struct measurespeed_frame f; + f.f.type = F_FRAME_MEASURE_SPEED_CMD; + f.f.size = sizeof(f); + f.hard_sector_count = (uint8_t) hardSectorCount; usb_cmd_send(&f, f.f.size); auto r = await_reply(F_FRAME_MEASURE_SPEED_REPLY); @@ -159,7 +161,9 @@ class FluxEngineUsb : public USB void testBulkWrite() { - struct any_frame f = { .f = {.type = F_FRAME_BULK_WRITE_TEST_CMD, .size = sizeof(f)} }; + struct any_frame f; + f.f.type = F_FRAME_BULK_WRITE_TEST_CMD; + f.f.size = sizeof(f); usb_cmd_send(&f, f.f.size); /* These must match the device. */ @@ -198,7 +202,9 @@ class FluxEngineUsb : public USB void testBulkRead() { - struct any_frame f = { .f = {.type = F_FRAME_BULK_READ_TEST_CMD, .size = sizeof(f)} }; + struct any_frame f; + f.f.type = F_FRAME_BULK_READ_TEST_CMD; + f.f.size = sizeof(f); usb_cmd_send(&f, f.f.size); /* These must match the device. */ @@ -234,11 +240,11 @@ class FluxEngineUsb : public USB Bytes read(int side, bool synced, nanoseconds_t readTime, nanoseconds_t hardSectorThreshold) { - struct read_frame f = { - .f = { .type = F_FRAME_READ_CMD, .size = sizeof(f) }, - .side = (uint8_t) side, - .synced = (uint8_t) synced, - }; + struct read_frame f; + f.f.type = F_FRAME_READ_CMD; + f.f.size = sizeof(f); + f.side = (uint8_t) side; + f.synced = (uint8_t) synced; f.hardsec_threshold_ms = (hardSectorThreshold + 5e5) / 1e6; /* round to nearest ms */ uint16_t milliseconds = readTime / 1e6; ((uint8_t*)&f.milliseconds)[0] = milliseconds; @@ -260,10 +266,10 @@ class FluxEngineUsb : public USB unsigned safelen = bytes.size() & ~(FRAME_SIZE-1); Bytes safeBytes = bytes.slice(0, safelen); - struct write_frame f = { - .f = { .type = F_FRAME_WRITE_CMD, .size = sizeof(f) }, - .side = (uint8_t) side, - }; + struct write_frame f; + f.f.type = F_FRAME_WRITE_CMD; + f.f.size = sizeof(f); + f.side = (uint8_t) side; f.hardsec_threshold_ms = (hardSectorThreshold + 5e5) / 1e6; /* round to nearest ms */ ((uint8_t*)&f.bytes_to_write)[0] = safelen; ((uint8_t*)&f.bytes_to_write)[1] = safelen >> 8; @@ -278,10 +284,10 @@ class FluxEngineUsb : public USB void erase(int side, nanoseconds_t hardSectorThreshold) { - struct erase_frame f = { - .f = { .type = F_FRAME_ERASE_CMD, .size = sizeof(f) }, - .side = (uint8_t) side, - }; + struct erase_frame f; + f.f.type = F_FRAME_ERASE_CMD; + f.f.size = sizeof(f); + f.side = (uint8_t) side; f.hardsec_threshold_ms = (hardSectorThreshold + 5e5) / 1e6; /* round to nearest ms */ usb_cmd_send(&f, f.f.size); @@ -290,21 +296,21 @@ class FluxEngineUsb : public USB void setDrive(int drive, bool high_density, int index_mode) { - struct set_drive_frame f = { - .f = { .type = F_FRAME_SET_DRIVE_CMD, .size = sizeof(f) }, - .drive = (uint8_t) drive, - .high_density = high_density, - .index_mode = (uint8_t) index_mode - }; + struct set_drive_frame f; + f.f.type = F_FRAME_SET_DRIVE_CMD; + f.f.size = sizeof(f); + f.drive = (uint8_t) drive; + f.high_density = high_density; + f.index_mode = (uint8_t) index_mode; usb_cmd_send(&f, f.f.size); await_reply(F_FRAME_SET_DRIVE_REPLY); } void measureVoltages(struct voltages_frame* voltages) { - struct any_frame f = { - { .type = F_FRAME_MEASURE_VOLTAGES_CMD, .size = sizeof(f) }, - }; + struct any_frame f; + f.f.type = F_FRAME_MEASURE_VOLTAGES_CMD; + f.f.size = sizeof(f); usb_cmd_send(&f, f.f.size); auto convert_voltages_from_usb = [&](const struct voltages& vin, struct voltages& vout) diff --git a/mkninja.sh b/mkninja.sh index fad4b8351..6e35147aa 100644 --- a/mkninja.sh +++ b/mkninja.sh @@ -418,6 +418,7 @@ FORMATS="\ ibm360_525 \ ibm720 \ ibm720_525 \ + kaypro2 \ mac400 \ mac800 \ micropolis \ @@ -523,6 +524,7 @@ encodedecodetest ibm180_525 encodedecodetest ibm360_525 encodedecodetest ibm720 encodedecodetest ibm720_525 +encodedecodetest kaypro2 encodedecodetest tids990 encodedecodetest commodore1581 encodedecodetest commodore1541 scripts/commodore1541_test.textpb diff --git a/src/formats/kaypro2.textpb b/src/formats/kaypro2.textpb new file mode 100644 index 000000000..dba6833db --- /dev/null +++ b/src/formats/kaypro2.textpb @@ -0,0 +1,73 @@ +comment: 'Kaypro II 5.25" 40-track 10-sector SSDD' + +image_reader { + filename: "kaypro2.img" + img { + trackdata { + sector_size: 512 + sector_range { + start_sector: 0 + sector_count: 10 + } + } + tracks: 40 + sides: 1 + physical_step: 1 + } +} + +image_writer { + filename: "kaypro2.img" + img { + trackdata { + sector_size: 512 + sector_range { + start_sector: 0 + sector_count: 10 + } + } + tracks: 40 + sides: 1 + physical_step: 1 + } +} + +encoder { + ibm { + trackdata { + emit_iam: false + track_length_ms: 167 + clock_rate_khz: 300 + sectors { + sector: 0 + sector: 1 + sector: 2 + sector: 3 + sector: 4 + sector: 5 + sector: 6 + sector: 7 + sector: 8 + sector: 9 + } + gap0: 80 + gap2: 22 + gap3: 44 + } + } +} + +decoder { + ibm {} +} + +cylinders { + start: 0 + end: 39 +} + +heads { + start: 0 + end: 0 +} +