diff options
author | 2019-03-25 22:44:58 +0100 | |
---|---|---|
committer | 2019-03-25 22:44:58 +0100 | |
commit | c24473ddff715ecec2e258a6eb38960cf8c8e98e (patch) | |
tree | 8ea44b6396a6129913c0aac13859b5de9965e972 /src/lib/formats/hpi_dsk.cpp | |
parent | 009cba4fb8102102168ef32870892438327f3705 (diff) | |
parent | 598cd5227223c3b04ca31f0dbc1981256d9ea3ff (diff) |
conflict resolution (nw)
Diffstat (limited to 'src/lib/formats/hpi_dsk.cpp')
-rw-r--r-- | src/lib/formats/hpi_dsk.cpp | 96 |
1 files changed, 78 insertions, 18 deletions
diff --git a/src/lib/formats/hpi_dsk.cpp b/src/lib/formats/hpi_dsk.cpp index 8d23f151862..50d2653280d 100644 --- a/src/lib/formats/hpi_dsk.cpp +++ b/src/lib/formats/hpi_dsk.cpp @@ -4,9 +4,10 @@ hpi_dsk.cpp - HP9895A "HPI" disk images + HP9885/HP9895A "HPI" disk images - CHS = 77/2/30 + CHS = 67/1/30 (SSDD) + CHS = 77/2/30 (DSDD) Sector size 256 bytes Cell size 2 µs Gap1 = 16 x 0x00 @@ -40,7 +41,7 @@ 256 bytes per sector). There's also a "reduced" version holding just 75 cylinders. When loading, the disk image is translated to MMFM encoding so - that it can be loaded into HP9895 emulator. + that it can be loaded into HP9885/HP9895 emulator. *********************************************************************/ @@ -65,11 +66,14 @@ constexpr int ID_DATA_OFFSET = 30 * 16; // Nominal distance (in cells) between I // Size of image file (holding 77 cylinders) constexpr unsigned HPI_IMAGE_SIZE = HPI_TRACKS * HPI_HEADS * HPI_SECTORS * HPI_SECTOR_SIZE; constexpr unsigned HPI_RED_TRACKS = 75; // Reduced number of tracks +constexpr unsigned HPI_9885_TRACKS = 67; // Tracks visible to HP9885 drives // Size of reduced image file (holding 75 cylinders) constexpr unsigned HPI_RED_IMAGE_SIZE = HPI_RED_TRACKS * HPI_HEADS * HPI_SECTORS * HPI_SECTOR_SIZE; hpi_format::hpi_format() { + (void)HPI_IMAGE_SIZE; + (void)HPI_RED_IMAGE_SIZE; } int hpi_format::identify(io_generic *io, uint32_t form_factor) @@ -79,27 +83,79 @@ int hpi_format::identify(io_generic *io, uint32_t form_factor) // we try to stay back and give only 50 points, since another image // format may also have images of the same size (there is no header and no // magic number for HPI format... + unsigned dummy_heads; + unsigned dummy_tracks; if (((form_factor == floppy_image::FF_8) || (form_factor == floppy_image::FF_UNKNOWN)) && - ((size == HPI_RED_IMAGE_SIZE) || (size == HPI_IMAGE_SIZE))) { + geometry_from_size(size , dummy_heads , dummy_tracks)) { return 50; } else { return 0; } } +bool hpi_format::geometry_from_size(uint64_t image_size , unsigned& heads , unsigned& tracks) +{ + if ((image_size % HPI_SECTOR_SIZE) != 0) { + // Not a whole number of sectors + return false; + } + unsigned sectors = unsigned(image_size / HPI_SECTOR_SIZE); + if ((sectors % HPI_SECTORS) != 0) { + // Not a whole number of tracks + return false; + } + unsigned tot_tracks = sectors / HPI_SECTORS; + // Possible combinations + // + // | Tot tracks | Heads | Tracks | Format | + // |------------+-------+--------+--------| + // | 67 | 1 | 67 | SSDD | + // | 77 | 1 | 77 | SSDD | + // | 150 | 2 | 75 | DSDD | + // | 154 | 2 | 77 | DSDD | + // + switch (tot_tracks) { + case HPI_9885_TRACKS: + heads = 1; + tracks = HPI_9885_TRACKS; + return true; + + case HPI_TRACKS: + heads = 1; + tracks = HPI_TRACKS; + return true; + + case HPI_RED_TRACKS * 2: + heads = 2; + tracks = HPI_RED_TRACKS; + return true; + + case HPI_TRACKS * 2: + heads = 2; + tracks = HPI_TRACKS; + return true; + + default: + return false; + } +} + bool hpi_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) { - image->set_variant(floppy_image::DSDD); // We actually need to derive the variant from the image size depending on the form factor + unsigned heads; + unsigned cylinders; uint64_t size = io_generic_size(io); - unsigned cylinders; - if (size == HPI_RED_IMAGE_SIZE) { - cylinders = HPI_RED_TRACKS; - } else if (size == HPI_IMAGE_SIZE) { - cylinders = HPI_TRACKS; - } else { + if (!geometry_from_size(size, heads, cylinders)) { + return false; + } + int max_tracks; + int max_heads; + image->get_maximal_geometry(max_tracks , max_heads); + if (cylinders > max_tracks || heads > max_heads) { return false; } + image->set_variant(heads == 2 ? floppy_image::DSDD : floppy_image::SSDD); // Suck in the whole image std::vector<uint8_t> image_data(size); @@ -118,11 +174,11 @@ bool hpi_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) unsigned list_offset = 0; for (unsigned cyl = 0; cyl < cylinders; cyl++) { - for (unsigned head = 0; head < HPI_HEADS; head++) { + for (unsigned head = 0; head < heads; head++) { std::vector<uint32_t> track_data; for (unsigned sector = 0; sector < HPI_SECTORS; sector++) { unsigned real_sector = sector_list[ (sector + list_offset) % HPI_SECTORS ]; - unsigned offset_in_image = chs_to_lba(cyl, head, real_sector) * HPI_SECTOR_SIZE; + unsigned offset_in_image = chs_to_lba(cyl, head, real_sector, heads) * HPI_SECTOR_SIZE; write_sector(track_data , cyl , real_sector + (head << 7) , &image_data[ offset_in_image ]); } fill_with_gap3(track_data); @@ -135,8 +191,12 @@ bool hpi_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) bool hpi_format::save(io_generic *io, floppy_image *image) { - for (unsigned cyl = 0; cyl < HPI_TRACKS; cyl++) { - for (unsigned head = 0; head < HPI_HEADS; head++) { + int tracks; + int heads; + image->get_actual_geometry(tracks, heads); + + for (int cyl = 0; cyl < tracks; cyl++) { + for (int head = 0; head < heads; head++) { uint8_t bitstream[ 21000 ]; int bitstream_size; generate_bitstream_from_track(cyl , head , CELL_SIZE , bitstream , bitstream_size , image , 0); @@ -145,7 +205,7 @@ bool hpi_format::save(io_generic *io, floppy_image *image) uint8_t sector_data[ HPI_SECTOR_SIZE ]; while (get_next_sector(bitstream , bitstream_size , pos , track_no , head_no , sector_no , sector_data)) { if (track_no == cyl && head_no == head && sector_no < HPI_SECTORS) { - unsigned offset_in_image = chs_to_lba(cyl, head, sector_no) * HPI_SECTOR_SIZE; + unsigned offset_in_image = chs_to_lba(cyl, head, sector_no, heads) * HPI_SECTOR_SIZE; io_generic_write(io, sector_data, offset_in_image, HPI_SECTOR_SIZE); } } @@ -300,9 +360,9 @@ void hpi_format::fill_with_gap3(std::vector<uint32_t> &buffer) } } -unsigned hpi_format::chs_to_lba(unsigned cylinder , unsigned head , unsigned sector) +unsigned hpi_format::chs_to_lba(unsigned cylinder , unsigned head , unsigned sector , unsigned heads) { - return sector + (head + cylinder * HPI_HEADS) * HPI_SECTORS; + return sector + (head + cylinder * heads) * HPI_SECTORS; } std::vector<uint8_t> hpi_format::get_next_id_n_block(const uint8_t *bitstream , int bitstream_size , int& pos , int& start_pos) |