diff options
Diffstat (limited to 'src/lib/formats/sdf_dsk.cpp')
-rw-r--r-- | src/lib/formats/sdf_dsk.cpp | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/lib/formats/sdf_dsk.cpp b/src/lib/formats/sdf_dsk.cpp new file mode 100644 index 00000000000..ab01de3b84a --- /dev/null +++ b/src/lib/formats/sdf_dsk.cpp @@ -0,0 +1,196 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol, tim lindner +/********************************************************************* + + formats/sdf_dsk.h + + SDF disk images. Format created by Darren Atkinson for use with + his CoCoSDC floppy disk emulator. + + http://cocosdc.blogspot.com/p/sd-card-socket-sd-card-socket-is-push.html + +*********************************************************************/ + +#include "sdf_dsk.h" +#include <assert.h> + +sdf_format::sdf_format() +{ +} + + +const char *sdf_format::name() const +{ + return "sdf"; +} + + +const char *sdf_format::description() const +{ + return "SDF disk image"; +} + + +const char *sdf_format::extensions() const +{ + return "sdf"; +} + + +int sdf_format::identify(io_generic *io, uint32_t form_factor) +{ + uint8_t header[HEADER_SIZE]; + + uint64_t size = io_generic_size(io); + + if (size < HEADER_SIZE) + { + return 0; + } + + io_generic_read(io, header, 0, HEADER_SIZE); + + int tracks = header[4]; + int heads = header[5]; + + // Check magic bytes + if (header[0] != 'S' || header[1] != 'D' || header[2] != 'F' || header[3] != '1') + { + return 0; + } + + // Check heads + if (heads != 1 && heads != 2) + { + return 0; + } + + if (size == HEADER_SIZE + heads * tracks * TOTAL_TRACK_SIZE) + { + return 100; + } + + return 0; +} + + +bool sdf_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) +{ + uint8_t header[HEADER_SIZE]; + std::vector<uint8_t> track_data(TOTAL_TRACK_SIZE); + std::vector<uint32_t> raw_track_data; + + io_generic_read(io, header, 0, HEADER_SIZE); + + const int tracks = header[4]; + const int heads = header[5]; + + if (heads == 2) + { + image->set_variant(floppy_image::DSDD); + } + else + { + image->set_variant(floppy_image::SSDD); + } + + for (int track = 0; track < tracks; track++) + { + for (int head = 0; head < heads; head++) + { + int iam_location = -1; + int idam_location[SECTOR_SLOT_COUNT+1]; + int dam_location[SECTOR_SLOT_COUNT+1]; + raw_track_data.clear(); + + // Read track + io_generic_read(io, &track_data[0], HEADER_SIZE + ( heads * track + head ) * TOTAL_TRACK_SIZE, TOTAL_TRACK_SIZE); + + int sector_count = track_data[0]; + + if (sector_count > SECTOR_SLOT_COUNT) return false; + + // Transfer IDAM and DAM locations to table + for (int i = 0; i < SECTOR_SLOT_COUNT+1; i++) + { + if (i < sector_count ) + { + idam_location[i] = ((track_data[ 8 * (i+1) + 1] << 8 | track_data[ 8 * (i+1)]) & 0x3FFF) - 4; + dam_location[i] = ((track_data[ 8 * (i+1) + 1 + 2] << 8 | track_data[ 8 * (i+1) + 2]) & 0x3FFF) - 4; + + if (idam_location[i] > TOTAL_TRACK_SIZE) return false; + if (dam_location[i] > TOTAL_TRACK_SIZE) return false; + } + else + { + idam_location[i] = -1; + dam_location[i] = -1; + } + } + + // Find IAM location + for (int i = idam_location[0] - 1; i >= TRACK_HEADER_SIZE + 3; i--) + { + // It's usually 3 bytes but several dumped tracks seem to contain only 2 bytes + if (track_data[i] == 0xfc && track_data[i-1] == 0xc2 && track_data[i-2] == 0xc2) + { + iam_location = i - 3; + break; + } + } + + int idam_index = 0; + int dam_index = 0; + for (int offset = TRACK_HEADER_SIZE; offset < TRACK_HEADER_SIZE + TRACK_SIZE; offset++) + { + if (offset == iam_location) + { + // Write IAM + raw_w(raw_track_data, 16, 0x5224); + raw_w(raw_track_data, 16, 0x5224); + raw_w(raw_track_data, 16, 0x5224); + offset += 3; + } + + if (offset == idam_location[idam_index]) + { + raw_w(raw_track_data, 16, 0x4489); + raw_w(raw_track_data, 16, 0x4489); + raw_w(raw_track_data, 16, 0x4489); + idam_index += 1; + offset += 3; + } + + if (offset == dam_location[dam_index]) + { + raw_w(raw_track_data, 16, 0x4489); + raw_w(raw_track_data, 16, 0x4489); + raw_w(raw_track_data, 16, 0x4489); + dam_index += 1; + offset += 3; + } + + mfm_w(raw_track_data, 8, track_data[offset]); + } + + generate_track_from_levels(track, head, raw_track_data, 0, image); + } + } + + return true; +} + + +bool sdf_format::save(io_generic *io, floppy_image *image) +{ + return false; +} + + +bool sdf_format::supports_save() const +{ + return false; +} + + +const floppy_format_type FLOPPY_SDF_FORMAT = &floppy_image_format_creator<sdf_format>; |