diff options
Diffstat (limited to 'src/lib/formats/g64_dsk.cpp')
-rw-r--r-- | src/lib/formats/g64_dsk.cpp | 130 |
1 files changed, 80 insertions, 50 deletions
diff --git a/src/lib/formats/g64_dsk.cpp b/src/lib/formats/g64_dsk.cpp index d0fc182835d..177438dc9a6 100644 --- a/src/lib/formats/g64_dsk.cpp +++ b/src/lib/formats/g64_dsk.cpp @@ -2,7 +2,7 @@ // copyright-holders:Curt Coder /********************************************************************* - formats/g64_dsk.c + formats/g64_dsk.cpp Commodore 1541/1571 GCR disk image format @@ -10,8 +10,14 @@ *********************************************************************/ -#include "emu.h" // emu_fatalerror #include "formats/g64_dsk.h" +#include "imageutl.h" + +#include "ioprocs.h" +#include "multibyte.h" + +#include "osdcore.h" // osd_printf_* + #define G64_FORMAT_HEADER "GCR-1541" @@ -27,25 +33,33 @@ const uint32_t g64_format::c1541_cell_size[] = 3250 // 16MHz/13/4 }; -int g64_format::identify(io_generic *io, uint32_t form_factor) +int g64_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const { char h[8]; + auto const [err, actual] = read_at(io, 0, h, 8); + if (err || (8 != actual)) + return 0; + + if (!memcmp(h, G64_FORMAT_HEADER, 8)) + return FIFID_SIGN; - io_generic_read(io, h, 0, 8); - if (!memcmp(h, G64_FORMAT_HEADER, 8)) { - return 100; - } return 0; } -bool g64_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) +bool g64_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const { - uint64_t size = io_generic_size(io); - std::vector<uint8_t> img(size); - io_generic_read(io, &img[0], 0, size); + uint64_t size; + if (io.length(size)) + return false; + + auto const [err, img, actual] = read_at(io, 0, size); + if (err || (actual != size)) + return false; - if (img[POS_VERSION]) { - throw emu_fatalerror("g64_format: Unsupported version %u", img[POS_VERSION]); + if (img[POS_VERSION]) + { + osd_printf_error("g64_format: Unsupported version %u\n", img[POS_VERSION]); + return false; } int track_count = img[POS_TRACK_COUNT]; @@ -60,20 +74,26 @@ bool g64_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) uint32_t tpos = POS_TRACK_OFFSET + (track * 4); uint32_t spos = tpos + (track_count * 4); - uint32_t dpos = pick_integer_le(&img[0], tpos, 4); + uint32_t dpos = get_u32le(&img[tpos]); if (!dpos) continue; if (dpos > size) - throw emu_fatalerror("g64_format: Track %u offset %06x out of bounds", track, dpos); + { + osd_printf_error("g64_format: Track %u offset %06x out of bounds\n", track, dpos); + return false; + } - uint32_t speed_zone = pick_integer_le(&img[0], spos, 4); + uint32_t speed_zone = get_u32le(&img[spos]); if (speed_zone > 3) - throw emu_fatalerror("g64_format: Unsupported variable speed zones on track %d", track); + { + osd_printf_error("g64_format: Unsupported variable speed zones on track %d\n", track); + return false; + } - uint16_t track_bytes = pick_integer_le(&img[0], dpos, 2); + uint16_t track_bytes = get_u16le(&img[dpos]); int track_size = track_bytes * 8; LOG_FORMATS("head %u track %u offs %u size %u cell %ld\n", head, cylinder, dpos, track_bytes, 200000000L/track_size); @@ -82,77 +102,87 @@ bool g64_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) } if (!head) - image->set_variant(floppy_image::SSSD); + image.set_variant(floppy_image::SSSD); else - image->set_variant(floppy_image::DSSD); + image.set_variant(floppy_image::DSSD); return true; } -int g64_format::generate_bitstream(int track, int head, int speed_zone, uint8_t *trackbuf, int &track_size, floppy_image *image) +int g64_format::generate_bitstream(int track, int head, int speed_zone, std::vector<bool> &trackbuf, const floppy_image &image) { int cell_size = c1541_cell_size[speed_zone]; - generate_bitstream_from_track(track, head, cell_size, trackbuf, track_size, image); + trackbuf = generate_bitstream_from_track(track, head, cell_size, image); - int actual_cell_size = 200000000L/track_size; + int actual_cell_size = 200000000L/trackbuf.size(); // allow a tolerance of +- 10 us (3990..4010 -> 4000) return ((actual_cell_size >= cell_size-10) && (actual_cell_size <= cell_size+10)) ? speed_zone : -1; } -bool g64_format::save(io_generic *io, floppy_image *image) +bool g64_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const { + uint8_t const zerofill[] = { 0x00, 0x00, 0x00, 0x00 }; + std::vector<uint8_t> const prefill(TRACK_LENGTH, 0xff); + int tracks, heads; - image->get_actual_geometry(tracks, heads); + image.get_actual_geometry(tracks, heads); tracks = TRACK_COUNT * heads; // write header uint8_t header[] = { 'G', 'C', 'R', '-', '1', '5', '4', '1', 0x00, static_cast<uint8_t>(tracks), TRACK_LENGTH & 0xff, TRACK_LENGTH >> 8 }; - io_generic_write(io, header, POS_SIGNATURE, sizeof(header)); + write_at(io, POS_SIGNATURE, header, sizeof(header)); // FIXME: check for errors // write tracks for (int head = 0; head < heads; head++) { int tracks_written = 0; - std::vector<uint8_t> trackbuf(TRACK_LENGTH-2); + std::vector<bool> trackbuf; for (int track = 0; track < TRACK_COUNT; track++) { - uint32_t tpos = POS_TRACK_OFFSET + (track * 4); - uint32_t spos = tpos + (tracks * 4); - uint32_t dpos = POS_TRACK_OFFSET + (tracks * 4 * 2) + (tracks_written * TRACK_LENGTH); + uint32_t const tpos = POS_TRACK_OFFSET + (track * 4); + uint32_t const spos = tpos + (tracks * 4); + uint32_t const dpos = POS_TRACK_OFFSET + (tracks * 4 * 2) + (tracks_written * TRACK_LENGTH); - io_generic_write_filler(io, 0x00, tpos, 4); - io_generic_write_filler(io, 0x00, spos, 4); + write_at(io, tpos, zerofill, 4); // FIXME: check for errors + write_at(io, spos, zerofill, 4); // FIXME: check for errors - if (image->get_buffer(track, head).size() <= 1) + if (image.get_buffer(track, head).size() <= 1) continue; int track_size; int speed_zone; // figure out the cell size and speed zone from the track data - if ((speed_zone = generate_bitstream(track, head, 3, &trackbuf[0], track_size, image)) == -1) - if ((speed_zone = generate_bitstream(track, head, 2, &trackbuf[0], track_size, image)) == -1) - if ((speed_zone = generate_bitstream(track, head, 1, &trackbuf[0], track_size, image)) == -1) - if ((speed_zone = generate_bitstream(track, head, 0, &trackbuf[0], track_size, image)) == -1) - throw emu_fatalerror("g64_format: Cannot determine speed zone for track %u", track); + if ((speed_zone = generate_bitstream(track, head, 3, trackbuf, image)) == -1) + if ((speed_zone = generate_bitstream(track, head, 2, trackbuf, image)) == -1) + if ((speed_zone = generate_bitstream(track, head, 1, trackbuf, image)) == -1) + if ((speed_zone = generate_bitstream(track, head, 0, trackbuf, image)) == -1) { + osd_printf_error("g64_format: Cannot determine speed zone for track %u\n", track); + return false; + } LOG_FORMATS("head %u track %u size %u cell %u\n", head, track, track_size, c1541_cell_size[speed_zone]); + std::vector<uint8_t> packed((trackbuf.size() + 7) >> 3, 0); + for(uint32_t i = 0; i != trackbuf.size(); i++) + if(trackbuf[i]) + packed[i >> 3] |= 0x80 >> (i & 7); + uint8_t track_offset[4]; uint8_t speed_offset[4]; uint8_t track_length[2]; - place_integer_le(track_offset, 0, 4, dpos); - place_integer_le(speed_offset, 0, 4, speed_zone); - place_integer_le(track_length, 0, 2, track_size/8); + put_u32le(track_offset, dpos); + put_u32le(speed_offset, speed_zone); + put_u16le(track_length, packed.size()); - io_generic_write(io, track_offset, tpos, 4); - io_generic_write(io, speed_offset, spos, 4); - io_generic_write_filler(io, 0xff, dpos, TRACK_LENGTH); - io_generic_write(io, track_length, dpos, 2); - io_generic_write(io, &trackbuf[0], dpos + 2, track_size); + write_at(io, tpos, track_offset, 4); // FIXME: check for errors + write_at(io, spos, speed_offset, 4); // FIXME: check for errors + write_at(io, dpos, prefill.data(), TRACK_LENGTH); // FIXME: check for errors + write_at(io, dpos, track_length, 2); // FIXME: check for errors + write_at(io, dpos + 2, packed.data(), packed.size()); // FIXME: check for errors tracks_written++; } @@ -161,19 +191,19 @@ bool g64_format::save(io_generic *io, floppy_image *image) return true; } -const char *g64_format::name() const +const char *g64_format::name() const noexcept { return "g64"; } -const char *g64_format::description() const +const char *g64_format::description() const noexcept { return "Commodore 1541/1571 GCR disk image"; } -const char *g64_format::extensions() const +const char *g64_format::extensions() const noexcept { return "g64,g41,g71"; } -const floppy_format_type FLOPPY_G64_FORMAT = &floppy_image_format_creator<g64_format>; +const g64_format FLOPPY_G64_FORMAT; |