From ec3dd7d7ea9e86b151c65564a568ef9f962e19bd Mon Sep 17 00:00:00 2001 From: Mike Wiese Date: Fri, 3 Nov 2023 23:44:49 -0700 Subject: [PATCH] apple2: Support 40 track 5.25 inch disk images - support 36 and 40 track .DO, .PO, and .DSK files - check file size is supported size - plumb MEDIATYPE_UNKNOWN errors in mount code --- lib/device/iwm/disk.cpp | 53 +++++++++++++++++--------------- lib/device/iwm/disk2.cpp | 15 +++++---- lib/device/iwm/disk2.h | 2 +- lib/media/apple/mediaTypeDO.cpp | 11 +++++++ lib/media/apple/mediaTypeDSK.cpp | 21 ++++++++++--- lib/media/apple/mediaTypeDSK.h | 3 +- lib/media/apple/mediaTypeWOZ.h | 1 - 7 files changed, 69 insertions(+), 37 deletions(-) diff --git a/lib/device/iwm/disk.cpp b/lib/device/iwm/disk.cpp index b5022ca6c..b9e818a87 100644 --- a/lib/device/iwm/disk.cpp +++ b/lib/device/iwm/disk.cpp @@ -502,8 +502,8 @@ iwmDisk::iwmDisk() mediatype_t iwmDisk::mount(FILE *f, const char *filename, uint32_t disksize, mediatype_t disk_type) { + mediatype_t mt = disk_type; uint8_t deviceSlot = data_buffer[0]; // from mount ctrl cmd - mediatype_t mt = MEDIATYPE_UNKNOWN; Debug_printf("disk MOUNT %s\n", filename); // Destroy any existing MediaType @@ -515,66 +515,71 @@ mediatype_t iwmDisk::mount(FILE *f, const char *filename, uint32_t disksize, med } // Determine MediaType based on filename extension - if (disk_type == MEDIATYPE_UNKNOWN && filename != nullptr) { - disk_type = MediaType::discover_mediatype(filename); - if (disk_type == MEDIATYPE_DSK) { - // determine DO or PO based on file contents - disk_type = MediaType::discover_dsk_mediatype(f, disksize); - } + if (mt == MEDIATYPE_UNKNOWN && filename != nullptr) { + mt = MediaType::discover_mediatype(filename); + } + + if (mt == MEDIATYPE_DSK) { + // determine DO or PO based on file contents + mt = MediaType::discover_dsk_mediatype(f, disksize); } if (deviceSlot < 4) // SP drive { - switch (disk_type) + switch (mt) { case MEDIATYPE_DO: Debug_printf("\r\nMedia Type DO"); _disk = new MediaTypeDO(); - _disk->_media_host = host; - _disk->_mediatype = disk_type; - strcpy(_disk->_disk_filename, filename); - mt = _disk->mount(f, disksize); - - device_active = true; //change status only after we are mounted break; case MEDIATYPE_PO: Debug_printf("\r\nMedia Type PO"); _disk = new MediaTypePO(); + break; + default: + Debug_printf("\r\nUnsupported Media Type for SmartPort"); + mt = MEDIATYPE_UNKNOWN; + break; + } + + if (mt != MEDIATYPE_UNKNOWN) { _disk->_media_host = host; - _disk->_mediatype = disk_type; + _disk->_mediatype = mt; strcpy(_disk->_disk_filename, filename); mt = _disk->mount(f, disksize); + } + if (mt != MEDIATYPE_UNKNOWN) { // firmware needs to believe a high score enabled disk is // not write-protected. Otherwise it will skip write process if (_disk->high_score_enabled) readonly = false; device_active = true; //change status only after we are mounted - break; - default: - Debug_printf("\r\nMedia Type UNKNOWN for SP Drive - no mount in disk.cpp"); - device_active = false; - break; } } else // DiskII drive { - switch (disk_type) + switch (mt) { case MEDIATYPE_DO: case MEDIATYPE_PO: case MEDIATYPE_WOZ: theFuji._fnDisk2s[deviceSlot - 4].init(); - theFuji._fnDisk2s[deviceSlot - 4].mount(f, disk_type); // modulo to ensure device 0 or 1 + mt = theFuji._fnDisk2s[deviceSlot - 4].mount(f, disksize, mt); break; default: - Debug_printf("\r\nMedia Type UNKNOWN for DiskII - no mount in disk.cpp"); - device_active = false; + Debug_printf("\r\nUnsupported Media Type for DiskII"); + mt = MEDIATYPE_UNKNOWN; break; } } + if (mt == MEDIATYPE_UNKNOWN) { + Debug_printf("\r\nMedia Type UNKNOWN - no mount in disk.cpp"); + device_active = false; + } + return mt; } diff --git a/lib/device/iwm/disk2.cpp b/lib/device/iwm/disk2.cpp index 5916a5632..1b23bbd9b 100644 --- a/lib/device/iwm/disk2.cpp +++ b/lib/device/iwm/disk2.cpp @@ -36,7 +36,7 @@ void iwmDisk2::init() device_active = false; } -mediatype_t iwmDisk2::mount(FILE *f, mediatype_t disk_type)//, const char *filename), uint32_t disksize, mediatype_t disk_type) +mediatype_t iwmDisk2::mount(FILE *f, uint32_t disksize, mediatype_t disk_type)//, const char *filename), uint32_t disksize, mediatype_t disk_type) { mediatype_t mt = MEDIATYPE_UNKNOWN; @@ -57,8 +57,7 @@ mediatype_t iwmDisk2::mount(FILE *f, mediatype_t disk_type)//, const char *filen Debug_printf("\nMounting Media Type WOZ"); device_active = true; _disk = new MediaTypeWOZ(); - mt = ((MediaTypeWOZ *)_disk)->mount(f); - change_track(0); // initialize spi buffer + mt = ((MediaTypeWOZ *)_disk)->mount(f, disksize); break; case MEDIATYPE_DO: case MEDIATYPE_PO: @@ -66,13 +65,17 @@ mediatype_t iwmDisk2::mount(FILE *f, mediatype_t disk_type)//, const char *filen device_active = true; _disk = new MediaTypeDSK(); _disk->_mediatype = disk_type; - mt = ((MediaTypeDSK *)_disk)->mount(f); - change_track(0); // initialize spi buffer + mt = ((MediaTypeDSK *)_disk)->mount(f, disksize); break; default: + break; + } + + if (mt == MEDIATYPE_WOZ) { + change_track(0); // initialize spi buffer + } else { Debug_printf("\nMedia Type UNKNOWN - no mount in disk2.cpp"); device_active = false; - break; } return mt; diff --git a/lib/device/iwm/disk2.h b/lib/device/iwm/disk2.h index f3007edfa..66a714a32 100644 --- a/lib/device/iwm/disk2.h +++ b/lib/device/iwm/disk2.h @@ -30,7 +30,7 @@ class iwmDisk2 : public iwmDevice public: iwmDisk2(); void init(); - mediatype_t mount(FILE *f, mediatype_t disk_type = MEDIATYPE_UNKNOWN); + mediatype_t mount(FILE *f, uint32_t disksize, mediatype_t disk_type = MEDIATYPE_UNKNOWN); void unmount(); bool write_blank(FILE *f, uint16_t sectorSize, uint16_t numSectors); int get_track_pos() { return track_pos; }; diff --git a/lib/media/apple/mediaTypeDO.cpp b/lib/media/apple/mediaTypeDO.cpp index ddfee8a57..0aa57e62c 100644 --- a/lib/media/apple/mediaTypeDO.cpp +++ b/lib/media/apple/mediaTypeDO.cpp @@ -90,6 +90,17 @@ bool MediaTypeDO::format(uint16_t *respopnsesize) mediatype_t MediaTypeDO::mount(FILE *f, uint32_t disksize) { + switch (disksize) { + case 35 * BYTES_PER_TRACK: + case 36 * BYTES_PER_TRACK: + case 40 * BYTES_PER_TRACK: + // 35, 36, and 40 tracks are supported (same as Applesauce) + break; + default: + Debug_printf("\nMediaTypeDO error: unsupported disk image size %ld", disksize); + return MEDIATYPE_UNKNOWN; + } + diskiiemulation = false; _media_fileh = f; num_blocks = disksize / BYTES_PER_BLOCK; diff --git a/lib/media/apple/mediaTypeDSK.cpp b/lib/media/apple/mediaTypeDSK.cpp index ccb40a27e..ee952406d 100644 --- a/lib/media/apple/mediaTypeDSK.cpp +++ b/lib/media/apple/mediaTypeDSK.cpp @@ -10,6 +10,7 @@ // #include // #include +#define BYTES_PER_TRACK 4096 // routines to convert DSK to WOZ stolen from DSK2WOZ by Tom Harte // https://github.com/TomHarte/dsk2woz @@ -19,11 +20,23 @@ static void serialise_track(uint8_t *dest, const uint8_t *src, uint8_t track_num mediatype_t MediaTypeDSK::mount(FILE *f, uint32_t disksize) { + switch (disksize) { + case 35 * BYTES_PER_TRACK: + case 36 * BYTES_PER_TRACK: + case 40 * BYTES_PER_TRACK: + // 35, 36, and 40 tracks are supported (same as Applesauce) + break; + default: + Debug_printf("\nMediaTypeDSK error: unsupported disk image size %ld", disksize); + return MEDIATYPE_UNKNOWN; + } + _media_fileh = f; diskiiemulation = true; + num_tracks = disksize / BYTES_PER_TRACK; // allocated SPRAM - const size_t dsk_image_size = 35 * 16 * 256; + const size_t dsk_image_size = num_tracks * BYTES_PER_TRACK; uint8_t *dsk = (uint8_t*)heap_caps_malloc(dsk_image_size, MALLOC_CAP_SPIRAM); if (fseek(f, 0, SEEK_SET) != 0) return MEDIATYPE_UNKNOWN; @@ -59,7 +72,7 @@ void MediaTypeDSK::dsk2woz_tmap() // Let's start by filling the entire TMAP with empty tracks. memset(tmap, 0xff, 160); // Then we will add in the mappings. - for(size_t c = 0; c < 35; ++c) + for(size_t c = 0; c < num_tracks; ++c) { size_t track_position = c << 2; if (c > 0) @@ -91,8 +104,8 @@ bool MediaTypeDSK::dsk2woz_tracks(uint8_t *dsk) Debug_printf("\nMediaTypeDSK is_prodos: %s", _mediatype == MEDIATYPE_PO ? "Y" : "N"); // TODO: adapt this to that - // Write out all 35 tracks. - for (size_t c = 0; c < 35; c++) + // Write out all tracks. + for (size_t c = 0; c < num_tracks; c++) { uint16_t bytes_used; uint16_t bit_count; diff --git a/lib/media/apple/mediaTypeDSK.h b/lib/media/apple/mediaTypeDSK.h index 99be02459..f2259712a 100644 --- a/lib/media/apple/mediaTypeDSK.h +++ b/lib/media/apple/mediaTypeDSK.h @@ -18,6 +18,8 @@ class MediaTypeDSK : public MediaTypeWOZ { private: + size_t num_tracks = 0; + void dsk2woz_info(); void dsk2woz_tmap(); bool dsk2woz_tracks(uint8_t *dsk); @@ -25,7 +27,6 @@ class MediaTypeDSK : public MediaTypeWOZ public: virtual mediatype_t mount(FILE *f, uint32_t disksize) override; - mediatype_t mount(FILE *f) {return mount(f, 0);}; // virtual void unmount() override; // static bool create(FILE *f, uint32_t numBlock); diff --git a/lib/media/apple/mediaTypeWOZ.h b/lib/media/apple/mediaTypeWOZ.h index 1251c836b..6e00a8920 100644 --- a/lib/media/apple/mediaTypeWOZ.h +++ b/lib/media/apple/mediaTypeWOZ.h @@ -40,7 +40,6 @@ class MediaTypeWOZ : public MediaType virtual bool format(uint16_t *respopnsesize) override { return false; }; virtual mediatype_t mount(FILE *f, uint32_t disksize) override; - mediatype_t mount(FILE *f) {return mount(f, 0);}; virtual void unmount() override; virtual bool status() override {return (_media_fileh != nullptr);}