From 27a04ee22b703a64edee315427249d52bf2b5288 Mon Sep 17 00:00:00 2001 From: dg Date: Mon, 27 Mar 2023 23:07:59 +0000 Subject: [PATCH] Add initial support for the Basis-108. --- README.md | 2 +- arch/apple2/apple2.proto | 8 +- arch/apple2/decoder.cc | 167 +++++++++++++++++++++----------------- src/formats/apple2.textpb | 90 +------------------- src/formats/build.mk | 2 + 5 files changed, 105 insertions(+), 164 deletions(-) diff --git a/README.md b/README.md index 3824f2e6..9b0200cf 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ people who've had it work). | [Acorn DFS](doc/disk-acorndfs.md) | 🦄 | 🦖* | | | [Ampro Little Board](doc/disk-ampro.md) | 🦖 | 🦖* | | | [Agat](doc/disk-agat.md) | 🦖 | | Soviet Union Apple-II-like computer | -| [Apple II](doc/disk-apple2.md) | 🦄 | 🦄 | | +| [Apple II](doc/disk-apple2.md) | 🦄 | 🦄 | also the Basis-108 clone | | [Amiga](doc/disk-amiga.md) | 🦄 | 🦄 | | | [Commodore 64 1541/1581](doc/disk-c64.md) | 🦄 | 🦄 | and probably the other formats | | [Brother 120kB](doc/disk-brother.md) | 🦄 | 🦄 | | diff --git a/arch/apple2/apple2.proto b/arch/apple2/apple2.proto index 50cea06d..11fe2023 100644 --- a/arch/apple2/apple2.proto +++ b/arch/apple2/apple2.proto @@ -2,7 +2,10 @@ syntax = "proto2"; import "lib/common.proto"; -message Apple2DecoderProto {} +message Apple2DecoderProto { + optional uint32 side_one_track_offset = 1 + [ default = 0, (help) = "offset to apply to track numbers on side 1" ]; +} message Apple2EncoderProto { @@ -13,4 +16,7 @@ message Apple2EncoderProto /* Apple II disk drives spin at 300rpm. */ optional double rotational_period_ms = 2 [ default = 200.0, (help) = "rotational period on the real device" ]; + + optional uint32 side_one_track_offset = 3 + [ default = 0, (help) = "offset to apply to track numbers on side 1" ]; } diff --git a/arch/apple2/decoder.cc b/arch/apple2/decoder.cc index a5d1062a..ce1e5b28 100644 --- a/arch/apple2/decoder.cc +++ b/arch/apple2/decoder.cc @@ -5,6 +5,8 @@ #include "decoders/decoders.h" #include "sector.h" #include "apple2.h" +#include "arch/apple2/apple2.pb.h" +#include "lib/decoders/decoders.pb.h" #include "bytes.h" #include "fmt/format.h" #include @@ -12,22 +14,25 @@ const FluxPattern SECTOR_RECORD_PATTERN(24, APPLE2_SECTOR_RECORD); const FluxPattern DATA_RECORD_PATTERN(24, APPLE2_DATA_RECORD); -const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN }); +const FluxMatchers ANY_RECORD_PATTERN( + {&SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN}); static int decode_data_gcr(uint8_t gcr) { switch (gcr) { - #define GCR_ENTRY(gcr, data) \ - case gcr: return data; - #include "data_gcr.h" - #undef GCR_ENTRY +#define GCR_ENTRY(gcr, data) \ + case gcr: \ + return data; +#include "data_gcr.h" +#undef GCR_ENTRY } return -1; } -/* This is extremely inspired by the MESS implementation, written by Nathan Woods - * and R. Belmont: https://github.com/mamedev/mame/blob/7914a6083a3b3a8c243ae6c3b8cb50b023f21e0e/src/lib/formats/ap2_dsk.cpp +/* This is extremely inspired by the MESS implementation, written by Nathan + * Woods and R. Belmont: + * https://github.com/mamedev/mame/blob/7914a6083a3b3a8c243ae6c3b8cb50b023f21e0e/src/lib/formats/ap2_dsk.cpp */ static Bytes decode_crazy_data(const uint8_t* inp, Sector::Status& status) { @@ -47,9 +52,11 @@ static Bytes decode_crazy_data(const uint8_t* inp, Sector::Status& status) { /* 3 * 2 bit */ output[i + 0] = ((checksum >> 1) & 0x01) | ((checksum << 1) & 0x02); - output[i + 86] = ((checksum >> 3) & 0x01) | ((checksum >> 1) & 0x02); + output[i + 86] = + ((checksum >> 3) & 0x01) | ((checksum >> 1) & 0x02); if ((i + 172) < APPLE2_SECTOR_LENGTH) - output[i + 172] = ((checksum >> 5) & 0x01) | ((checksum >> 3) & 0x02); + output[i + 172] = + ((checksum >> 5) & 0x01) | ((checksum >> 3) & 0x02); } } @@ -67,88 +74,102 @@ static uint8_t combine(uint16_t word) class Apple2Decoder : public Decoder { public: - Apple2Decoder(const DecoderProto& config): - Decoder(config) - {} + Apple2Decoder(const DecoderProto& config): Decoder(config) {} nanoseconds_t advanceToNextRecord() override - { - return seekToPattern(ANY_RECORD_PATTERN); - } + { + return seekToPattern(ANY_RECORD_PATTERN); + } void decodeSectorRecord() override - { - if (readRaw24() != APPLE2_SECTOR_RECORD) - return; + { + if (readRaw24() != APPLE2_SECTOR_RECORD) + return; - /* Read header. */ + /* Read header. */ - auto header = toBytes(readRawBits(8*8)).slice(0, 8); - ByteReader br(header); + auto header = toBytes(readRawBits(8 * 8)).slice(0, 8); + ByteReader br(header); - uint8_t volume = combine(br.read_be16()); - _sector->logicalTrack = combine(br.read_be16()); - _sector->logicalSector = combine(br.read_be16()); - uint8_t checksum = combine(br.read_be16()); + uint8_t volume = combine(br.read_be16()); + _sector->logicalTrack = combine(br.read_be16()); + _sector->logicalSide = _sector->physicalSide; + _sector->logicalSector = combine(br.read_be16()); + uint8_t checksum = combine(br.read_be16()); - // If the checksum is correct, upgrade the sector from MISSING - // to DATA_MISSING in anticipation of its data record - if (checksum == (volume ^ _sector->logicalTrack ^ _sector->logicalSector)) - _sector->status = Sector::DATA_MISSING; /* unintuitive but correct */ - } + // If the checksum is correct, upgrade the sector from MISSING + // to DATA_MISSING in anticipation of its data record + if (checksum == + (volume ^ _sector->logicalTrack ^ _sector->logicalSector)) + _sector->status = + Sector::DATA_MISSING; /* unintuitive but correct */ + + if (_sector->logicalSide == 1) + _sector->logicalTrack -= _config.apple2().side_one_track_offset(); + + /* Sanity check. */ + + if (_sector->logicalTrack > 100) + { + _sector->status = Sector::MISSING; + return; + } + } void decodeDataRecord() override - { - /* Check ID. */ + { + /* Check ID. */ - if (readRaw24() != APPLE2_DATA_RECORD) - return; + if (readRaw24() != APPLE2_DATA_RECORD) + return; - // Sometimes there's a 1-bit gap between APPLE2_DATA_RECORD and - // the data itself. This has been seen on real world disks - // such as the Apple II Operating System Kit from Apple2Online. - // However, I haven't seen it described in any of the various - // references. - // - // This extra '0' bit would not affect the real disk interface, - // as it was a '1' reaching the top bit of a shift register - // that triggered a byte to be available, but it affects the - // way the data is read here. - // - // While the floppies tested only seemed to need this applied - // to the first byte of the data record, applying it - // consistently to all of them doesn't seem to hurt, and - // simplifies the code. + // Sometimes there's a 1-bit gap between APPLE2_DATA_RECORD and + // the data itself. This has been seen on real world disks + // such as the Apple II Operating System Kit from Apple2Online. + // However, I haven't seen it described in any of the various + // references. + // + // This extra '0' bit would not affect the real disk interface, + // as it was a '1' reaching the top bit of a shift register + // that triggered a byte to be available, but it affects the + // way the data is read here. + // + // While the floppies tested only seemed to need this applied + // to the first byte of the data record, applying it + // consistently to all of them doesn't seem to hurt, and + // simplifies the code. - /* Read and decode data. */ + /* Read and decode data. */ - auto readApple8 = [&]() { - auto result = 0; - while((result & 0x80) == 0) { - auto b = readRawBits(1); - if(b.empty()) break; - result = (result << 1) | b[0]; - } - return result; - }; + auto readApple8 = [&]() + { + auto result = 0; + while ((result & 0x80) == 0) + { + auto b = readRawBits(1); + if (b.empty()) + break; + result = (result << 1) | b[0]; + } + return result; + }; - constexpr unsigned recordLength = APPLE2_ENCODED_SECTOR_LENGTH+2; - uint8_t bytes[recordLength]; - for(auto &byte : bytes) { - byte = readApple8(); - } + constexpr unsigned recordLength = APPLE2_ENCODED_SECTOR_LENGTH + 2; + uint8_t bytes[recordLength]; + for (auto& byte : bytes) + { + byte = readApple8(); + } - // Upgrade the sector from MISSING to BAD_CHECKSUM. - // If decode_crazy_data succeeds, it upgrades the sector to - // OK. - _sector->status = Sector::BAD_CHECKSUM; - _sector->data = decode_crazy_data(&bytes[0], _sector->status); - } + // Upgrade the sector from MISSING to BAD_CHECKSUM. + // If decode_crazy_data succeeds, it upgrades the sector to + // OK. + _sector->status = Sector::BAD_CHECKSUM; + _sector->data = decode_crazy_data(&bytes[0], _sector->status); + } }; std::unique_ptr createApple2Decoder(const DecoderProto& config) { - return std::unique_ptr(new Apple2Decoder(config)); + return std::unique_ptr(new Apple2Decoder(config)); } - - diff --git a/src/formats/apple2.textpb b/src/formats/apple2.textpb index 0e7d31ad..faaa90cb 100644 --- a/src/formats/apple2.textpb +++ b/src/formats/apple2.textpb @@ -1,4 +1,5 @@ comment: 'Apple II 140kB DOS 3.3 5.25" 40 track SSSD' +include: '_apple2' image_reader { filename: "apple2.img" @@ -22,94 +23,5 @@ image_writer { type: IMG } -decoder { - apple2 {} -} - -encoder { - apple2 {} -} - tpi: 48 -option { - name: "appledos" - comment: "specifies AppleDOS soft sector skew for filesystem access and images" - message: "compensating for AppleDOS soft sector skew" - - config { - image_reader { - filesystem_sector_order: true - } - - image_writer { - filesystem_sector_order: true - } - - layout { - layoutdata { - filesystem { - sector: 0 - sector: 14 - sector: 13 - sector: 12 - sector: 11 - sector: 10 - sector: 9 - sector: 8 - sector: 7 - sector: 6 - sector: 5 - sector: 4 - sector: 3 - sector: 2 - sector: 1 - sector: 15 - } - } - } - } -} - -option { - name: "prodos" - comment: "specifies ProDOS soft sector skew for filesystem access and images" - message: "compensating for ProDOS soft sector skew" - - config { - image_reader { - filesystem_sector_order: true - } - - image_writer { - filesystem_sector_order: true - } - - filesystem { - type: PRODOS - } - - layout { - layoutdata { - filesystem { - sector: 0 - sector: 2 - sector: 4 - sector: 6 - sector: 8 - sector: 10 - sector: 12 - sector: 14 - sector: 1 - sector: 3 - sector: 5 - sector: 7 - sector: 9 - sector: 11 - sector: 13 - sector: 15 - } - } - } - } -} \ No newline at end of file diff --git a/src/formats/build.mk b/src/formats/build.mk index 22f65c9e..89a4a35e 100644 --- a/src/formats/build.mk +++ b/src/formats/build.mk @@ -1,6 +1,7 @@ FORMATS = \ _acornadfs8 \ _acornadfs32 \ + _apple2 \ _atari \ _micropolis \ _northstar \ @@ -27,6 +28,7 @@ FORMATS = \ atarist740 \ atarist800 \ atarist820 \ + basis640 \ bk800 \ brother120 \ brother240 \