diff options
author | 2017-05-16 09:52:31 +0200 | |
---|---|---|
committer | 2017-05-16 09:52:31 +0200 | |
commit | e2b9e11da092a28c9a26940659e148c61aaa4822 (patch) | |
tree | 401e09eeb6bbdd3bcad84c44a54360a1ab2d252f | |
parent | dc1dcd260b8209b006e7958cf2226438ced490c2 (diff) |
Hp9845: Support for HPI floppy format (#2310)
hp9845: Support for HPI floppy format [F. Ulivi, A.Kückes]
-rw-r--r-- | scripts/src/formats.lua | 12 | ||||
-rw-r--r-- | scripts/target/mame/mess.lua | 1 | ||||
-rw-r--r-- | src/devices/bus/hp9845_io/98034.cpp | 15 | ||||
-rw-r--r-- | src/devices/bus/ieee488/hp9895.cpp | 11 | ||||
-rw-r--r-- | src/lib/formats/hpi_dsk.cpp | 430 | ||||
-rw-r--r-- | src/lib/formats/hpi_dsk.h | 55 | ||||
-rw-r--r-- | src/tools/floptool.cpp | 4 |
7 files changed, 520 insertions, 8 deletions
diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua index ba20df392a0..6129e45b2b6 100644 --- a/scripts/src/formats.lua +++ b/scripts/src/formats.lua @@ -895,6 +895,18 @@ end -------------------------------------------------- -- +--@src/lib/formats/hpi_dsk.h,FORMATS["HPI_DSK"] = true +-------------------------------------------------- + +if (FORMATS["HPI_DSK"]~=null or _OPTIONS["with-tools"]) then + files { + MAME_DIR.. "src/lib/formats/hpi_dsk.cpp", + MAME_DIR.. "src/lib/formats/hpi_dsk.h", + } +end + +-------------------------------------------------- +-- --@src/lib/formats/hp_ipc_dsk.h,FORMATS["HP_IPC_DSK"] = true -------------------------------------------------- diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index cbaa512d363..32f315c8b00 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -800,6 +800,7 @@ FORMATS["GTP_CAS"] = true FORMATS["HECTOR_MINIDISC"] = true FORMATS["HECT_DSK"] = true FORMATS["HECT_TAP"] = true +FORMATS["HPI_DSK"] = true FORMATS["HP_IPC_DSK"] = true FORMATS["IQ151_DSK"] = true FORMATS["ITT3030_DSK"] = true diff --git a/src/devices/bus/hp9845_io/98034.cpp b/src/devices/bus/hp9845_io/98034.cpp index c9a2f263259..37a679fa3c3 100644 --- a/src/devices/bus/hp9845_io/98034.cpp +++ b/src/devices/bus/hp9845_io/98034.cpp @@ -133,9 +133,12 @@ READ16_MEMBER(hp98034_io_card_device::reg_r) m_force_flg = true; update_flg(); - // PPU yields to let NP see FLG=0 immediately - // (horrible race conditions lurking...) - space.device().execute().yield(); + // PPU pauses for an instant to let NP see FLG=0 immediately + // There's a bug in Mass Memory opt. ROM because the PPU + // doesn't wait for FLG from 98034 in a few (common) cases. + // A magic combination of relative speeds between PPU and + // NP always hides this bug in the real hw. + space.device().execute().spin_until_time(attotime::from_usec(5)); LOG("read R%u=%04x\n" , offset + 4 , res); return res; @@ -156,9 +159,9 @@ WRITE16_MEMBER(hp98034_io_card_device::reg_w) m_force_flg = true; update_flg(); - // PPU yields to let NP see FLG=0 immediately - // (horrible race conditions lurking...) - space.device().execute().yield(); + // PPU pauses for an instant to let NP see FLG=0 immediately + // (see above) + space.device().execute().spin_until_time(attotime::from_usec(5)); LOG("write R%u=%04x\n" , offset + 4 , data); } diff --git a/src/devices/bus/ieee488/hp9895.cpp b/src/devices/bus/ieee488/hp9895.cpp index 6e5e62d6e53..73ab69a5e00 100644 --- a/src/devices/bus/ieee488/hp9895.cpp +++ b/src/devices/bus/ieee488/hp9895.cpp @@ -56,6 +56,7 @@ #include "emu.h" #include "hp9895.h" +#include "formats/hpi_dsk.h" // Debugging #define VERBOSE 1 @@ -866,6 +867,12 @@ static SLOT_INTERFACE_START(hp9895_floppies) SLOT_INTERFACE("8dsdd" , FLOPPY_8_DSDD) SLOT_INTERFACE_END +static const floppy_format_type hp9895_floppy_formats[] = { + FLOPPY_MFI_FORMAT, + FLOPPY_HPI_FORMAT, + nullptr +}; + static MACHINE_CONFIG_FRAGMENT(hp9895) MCFG_CPU_ADD("cpu" , Z80 , 4000000) MCFG_CPU_PROGRAM_MAP(z80_program_map) @@ -884,9 +891,9 @@ static MACHINE_CONFIG_FRAGMENT(hp9895) MCFG_PHI_DIO_READWRITE_CB(READ8(hp9895_device , phi_dio_r) , WRITE8(hp9895_device , phi_dio_w)) MCFG_PHI_INT_WRITE_CB(WRITELINE(hp9895_device , phi_int_w)) - MCFG_FLOPPY_DRIVE_ADD("floppy0" , hp9895_floppies , "8dsdd" , floppy_image_device::default_floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("floppy0" , hp9895_floppies , "8dsdd" , hp9895_floppy_formats) MCFG_SLOT_FIXED(true) - MCFG_FLOPPY_DRIVE_ADD("floppy1" , hp9895_floppies , "8dsdd" , floppy_image_device::default_floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("floppy1" , hp9895_floppies , "8dsdd" , hp9895_floppy_formats) MCFG_SLOT_FIXED(true) MACHINE_CONFIG_END diff --git a/src/lib/formats/hpi_dsk.cpp b/src/lib/formats/hpi_dsk.cpp new file mode 100644 index 00000000000..2f48f873f59 --- /dev/null +++ b/src/lib/formats/hpi_dsk.cpp @@ -0,0 +1,430 @@ +// license:BSD-3-Clause +// copyright-holders: Ansgar Kückes, F. Ulivi +/********************************************************************* + + hpi_dsk.cpp + + HP9895A "HPI" disk images + + CHS = 77/2/30 + Sector size 256 bytes + Cell size 2 µs + Gap1 = 16 x 0x00 + Gap2 = 34 x 0x00 + Gap3 = ~490 x 0x00 (depends on actual rotation speed) + Sync = 4 x 0x00 + 4 x 0xff + ID AM = 0x0e clock + 0x70 data + Data AM = 0x0e clock + 0x50 data + DefectTrack AM = 0x0e clock + 0xf0 data + CRC-16 excludes address markers + MMFM/M2FM encoding (LS bit first) + + The order of sectors in a track depends on the interleave factor + which is the distance (in number of sectors) between two consecutively + numbered sectors. Interleave factor is specified at formatting time. + The default factor is 7. The order of sectors for this factor is: + 0, 13, 26, 9, 22, 5, 18, 1, 14, 27, 10, 23, 6, 19, 2, + 15, 28, 11, 24, 7, 20, 3, 16, 29, 12, 25, 8, 21, 4, 17 + + <Track> := [Index hole]|Sector0|Gap2|Sector1|Gap2|...|Sector29|Gap3| + + <Sector> := ID field|Gap1|Data field + + <ID field> := Sync|ID AM|Track no.|Sector no.|CRC-16|0x00 + + <Data field> := Sync|Data AM|Data|CRC-16|0x00 + + This format is just a raw image of every sector on a HP-formatted + 8" floppy disk. Files with this format have no header/trailer and + are exactly 1182720 bytes in size (30 sectors, 2 heads, 77 tracks, + 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. + +*********************************************************************/ + +#include "emu.h" +#include "hpi_dsk.h" + +// Debugging +#define VERBOSE 0 +#define LOG(...) do { if (VERBOSE) printf(__VA_ARGS__); } while (false) + +constexpr unsigned IL_OFFSET = 0x12; // Position of interleave factor in HPI image (2 bytes, big-endian) +constexpr unsigned DEFAULT_IL = 7; // Default interleaving factor +constexpr unsigned CELL_SIZE = 1200; // Bit cell size (1 µs) +constexpr uint8_t ID_AM = 0x70; // ID address mark +constexpr uint8_t DATA_AM = 0x50; // Data address mark +constexpr uint8_t AM_CLOCK = 0x0e; // Clock pattern of AM +constexpr uint32_t ID_CD_PATTERN= 0x55552a54; // C/D pattern of 0xff + ID_AM +constexpr uint32_t DATA_CD_PATTERN = 0x55552a44; // C/D pattern of 0xff + DATA_AM +constexpr unsigned GAP1_SIZE = 17; // Size of gap 1 (+1) +constexpr unsigned GAP2_SIZE = 35; // Size of gap 2 (+1) +constexpr unsigned ID_DATA_OFFSET = 30 * 16; // Nominal distance (in cells) between ID & DATA AM +// 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 +// 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() +{ +} + +int hpi_format::identify(io_generic *io, uint32_t form_factor) +{ + uint64_t size = io_generic_size(io); + + // 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... + if (((form_factor == floppy_image::FF_8) || (form_factor == floppy_image::FF_UNKNOWN)) && + ((size == HPI_RED_IMAGE_SIZE) || (size == HPI_IMAGE_SIZE))) { + return 50; + } else { + return 0; + } +} + +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 + + 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 { + return false; + } + + // Suck in the whole image + std::vector<uint8_t> image_data(size); + io_generic_read(io, (void *)image_data.data(), 0, size); + + // Get interleave factor from image + unsigned il = (unsigned)image_data[ IL_OFFSET ] * 256 + image_data[ IL_OFFSET + 1 ]; + LOG("I/L from image: %u\n" , il); + if (il < 1 || il >= HPI_SECTORS) { + il = DEFAULT_IL; + } + LOG("Actual I/L: %u\n" , il); + + sector_list_t sector_list; + interleaved_sectors(il, sector_list); + + unsigned list_offset = 0; + for (unsigned cyl = 0; cyl < cylinders; cyl++) { + for (unsigned head = 0; head < HPI_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; + write_sector(track_data , cyl , real_sector + (head << 7) , &image_data[ offset_in_image ]); + } + fill_with_gap3(track_data); + generate_track_from_levels(cyl , head , track_data , 0 , image); + list_offset = (list_offset + m_track_skew[ il - 1 ][ head ]) % HPI_SECTORS; + } + } + return true; +} + +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++) { + uint8_t bitstream[ 21000 ]; + int bitstream_size; + generate_bitstream_from_track(cyl , head , CELL_SIZE , bitstream , bitstream_size , image , 0); + int pos = 0; + unsigned track_no , head_no , sector_no; + 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; + io_generic_write(io, sector_data, offset_in_image, HPI_SECTOR_SIZE); + } + } + } + } + return true; +} + +const char *hpi_format::name() const +{ + return "hpi"; +} + +const char *hpi_format::description() const +{ + return "HP9895A floppy disk image"; +} + +const char *hpi_format::extensions() const +{ + return "hpi"; +} + +bool hpi_format::supports_save() const +{ + return true; +} + +void hpi_format::interleaved_sectors(unsigned il_factor , sector_list_t& sector_list) +{ + sector_list.fill(0xff); + + unsigned idx = HPI_SECTORS - il_factor; + for (unsigned sect = 0; sect < HPI_SECTORS; sect++) { + idx = (idx + il_factor) % HPI_SECTORS; + while (sector_list[ idx ] != 0xff) { + idx = (idx + 1) % HPI_SECTORS; + } + LOG("[%u]=%u\n" , idx , sect); + sector_list[ idx ] = sect; + } +} + +void hpi_format::write_mmfm_bit(std::vector<uint32_t> &buffer , bool data_bit , bool clock_bit) +{ + bool had_transition = buffer.size() < 2 ? false : bit_r(buffer, buffer.size() - 1) || bit_r(buffer , buffer.size() - 2); + clock_bit = !data_bit && (clock_bit || !had_transition); + bit_w(buffer , clock_bit , CELL_SIZE); + bit_w(buffer , data_bit , CELL_SIZE); +} + +void hpi_format::write_mmfm_byte(std::vector<uint32_t> &buffer , uint8_t data , uint8_t clock) +{ + for (unsigned i = 0; i < 8; i++) { + write_mmfm_bit(buffer , BIT(data , i) , BIT(clock , i)); + } +} + +void hpi_format::write_sync(std::vector<uint32_t> &buffer) +{ + // Sync + // 4x 00 + for (unsigned i = 0; i < 4; i++) { + write_mmfm_byte(buffer , 0); + } + // 4x ff + for (unsigned i = 0; i < 4; i++) { + write_mmfm_byte(buffer , 0xff); + } +} + +void hpi_format::write_crc(std::vector<uint32_t> &buffer , uint16_t crc) +{ + // Note that CRC is stored with MSB (x^15) first + for (unsigned i = 0; i < 16; i++) { + write_mmfm_bit(buffer , BIT(crc , 15 - i) , 0); + } +} + +void hpi_format::write_sector(std::vector<uint32_t> &buffer , uint8_t track_no , uint8_t sect_head_no , const uint8_t *sect_data) +{ + // **** On-disk format of a sector **** + // + // | Offset | Size | Value | Content | + // |--------+------+-------+----------------------| + // | 0 | 4 | 00 | Sync | + // | 4 | 4 | ff | Sync | + // | 8 | 1 | 70 | ID AM (clock = 0e) | + // | 9 | 1 | xx | Track no. | + // | 10 | 1 | xx | Sector and head no. | + // | 11 | 2 | xx | ID CRC | + // | 13 | 1 | 00 | ID tail | + // | 14 | 16 | 00 | Gap 1 | + // | 30 | 4 | 00 | Sync | + // | 34 | 4 | ff | Sync | + // | 38 | 1 | 50 | Data AM (clock = 0e) | + // | 39 | 256 | xx | Sector data | + // | 295 | 2 | xx | Data CRC | + // | 297 | 1 | 00 | Data tail | + // | 298 | 34 | 00 | Gap 2 | + // | 332 | | | | + + // Sync + write_sync(buffer); + // ID AM + write_mmfm_byte(buffer , ID_AM , AM_CLOCK); + auto crc_start = buffer.size(); + // Track # + write_mmfm_byte(buffer , track_no); + // Sector/head # + write_mmfm_byte(buffer , sect_head_no); + uint16_t crc = calc_crc_ccitt(buffer , crc_start , buffer.size()); + // ID CRC + write_crc(buffer , crc); + // Gap 1 + for (unsigned i = 0; i < GAP1_SIZE; i++) { + write_mmfm_byte(buffer , 0); + } + // Sync + write_sync(buffer); + // Data AM + write_mmfm_byte(buffer , DATA_AM , AM_CLOCK); + crc_start = buffer.size(); + for (unsigned i = 0; i < HPI_SECTOR_SIZE; i += 2) { + // Data: bytes are swapped in pairs + write_mmfm_byte(buffer , sect_data[ i + 1 ]); + write_mmfm_byte(buffer , sect_data[ i ]); + } + crc = calc_crc_ccitt(buffer , crc_start , buffer.size()); + // Data CRC + write_crc(buffer , crc); + // Gap 2 + for (unsigned i = 0; i < GAP2_SIZE; i++) { + write_mmfm_byte(buffer , 0); + } +} + +void hpi_format::fill_with_gap3(std::vector<uint32_t> &buffer) +{ + // Cell count in a track (1 µs cells in a 1/6 s track) + unsigned cell_count = (500000 * 120) / 360; + unsigned cells_in_buffer = buffer.size(); + // Size of gap 3 + unsigned gap_3 = (cell_count - cells_in_buffer) / 16; + // Gap 3 + for (unsigned i = 0; i < gap_3; i++) { + write_mmfm_byte(buffer , 0); + } + // Last cell to round everything up to 2E+8 + if (buffer.size() * CELL_SIZE < 200000000) { + bit_w(buffer , false , 200000000 - buffer.size() * CELL_SIZE); + } +} + +unsigned hpi_format::chs_to_lba(unsigned cylinder , unsigned head , unsigned sector) +{ + return sector + (head + cylinder * HPI_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) +{ + std::vector<uint8_t> res; + uint32_t sr = 0; + // Look for either sync + ID AM or sync + DATA AM + while (pos < bitstream_size && sr != ID_CD_PATTERN && sr != DATA_CD_PATTERN) { + bool bit = BIT(bitstream[ pos >> 3 ] , 7 - (pos & 7)); + pos++; + sr = (sr << 1) | bit; + } + if (pos == bitstream_size) { + // End of track reached + return res; + } + start_pos = pos; + // ID blocks: Track no. + sector/head no. + CRC + // Data blocks: Sector data + CRC + unsigned to_dump; + if (sr == ID_CD_PATTERN) { + to_dump = 4; + res.push_back(ID_AM); + } else { + to_dump = HPI_SECTOR_SIZE + 2; + res.push_back(DATA_AM); + } + // Align to data cells + pos++; + for (unsigned i = 0; i < to_dump && pos < bitstream_size; i++) { + uint8_t byte = 0; + unsigned j; + for (j = 0; j < 8 && pos < bitstream_size; j++) { + bool bit = BIT(bitstream[ pos >> 3 ] , 7 - (pos & 7)); + pos += 2; + byte >>= 1; + if (bit) { + byte |= 0x80; + } + } + if (j == 8) { + res.push_back(byte); + } + } + return res; +} + +bool hpi_format::get_next_sector(const uint8_t *bitstream , int bitstream_size , int& pos , unsigned& track , unsigned& head , unsigned& sector , uint8_t *sector_data) +{ + std::vector<uint8_t> block; + while (true) { + // Scan for ID block first + int id_pos; + while (true) { + if (block.size() == 0) { + block = get_next_id_n_block(bitstream , bitstream_size , pos , id_pos); + if (block.size() == 0) { + return false; + } + } + if (block[ 0 ] == ID_AM && block.size() >= 3) { + track = block[ 1 ]; + head = block[ 2 ] >> 7; + sector = block[ 2 ] & 0x7f; + break; + } else { + block.clear(); + } + } + // Then for DATA block + int data_pos; + block = get_next_id_n_block(bitstream , bitstream_size , pos , data_pos); + if (block.size() == 0) { + return false; + } + if (block[ 0 ] == DATA_AM && block.size() >= (HPI_SECTOR_SIZE + 1) && abs((data_pos - id_pos) - ID_DATA_OFFSET) <= 16) { + break; + } + } + + for (unsigned i = 0; i < HPI_SECTOR_SIZE; i += 2) { + sector_data[ i ] = block[ i + 2 ]; + sector_data[ i + 1 ] = block[ i + 1 ]; + } + + return true; +} + +// This table comes straight from hp9895 firmware (it's @ 0x0f90) +// For each interleave factor in [1..29] it stores the number of positions +// to move forward in the interleaved sector list when beginning a new track. +// There are different offsets for tracks on head 0 and tracks on head 1. +const uint8_t hpi_format::m_track_skew[ HPI_SECTORS - 1 ][ HPI_HEADS ] = { + { 0x1c , 0x18 }, // Interleave = 1 + { 0x1c , 0x18 }, // Interleave = 2 + { 0x1c , 0x18 }, // Interleave = 3 + { 0x1d , 0x1a }, // Interleave = 4 + { 0x1a , 0x18 }, // Interleave = 5 + { 0x19 , 0x18 }, // Interleave = 6 + { 0x00 , 0x00 }, // Interleave = 7 + { 0x1d , 0x1d }, // Interleave = 8 + { 0x1c , 0x1c }, // Interleave = 9 + { 0x15 , 0x15 }, // Interleave = 10 + { 0x00 , 0x00 }, // Interleave = 11 + { 0x19 , 0x19 }, // Interleave = 12 + { 0x00 , 0x00 }, // Interleave = 13 + { 0x1d , 0x1d }, // Interleave = 14 + { 0x10 , 0x10 }, // Interleave = 15 + { 0x1d , 0x1d }, // Interleave = 16 + { 0x00 , 0x00 }, // Interleave = 17 + { 0x19 , 0x19 }, // Interleave = 18 + { 0x00 , 0x00 }, // Interleave = 19 + { 0x15 , 0x15 }, // Interleave = 20 + { 0x1c , 0x1c }, // Interleave = 21 + { 0x1d , 0x1d }, // Interleave = 22 + { 0x00 , 0x00 }, // Interleave = 23 + { 0x19 , 0x19 }, // Interleave = 24 + { 0x1a , 0x1a }, // Interleave = 25 + { 0x1d , 0x1d }, // Interleave = 26 + { 0x1c , 0x1c }, // Interleave = 27 + { 0x1d , 0x1d }, // Interleave = 28 + { 0x00 , 0x00 } // Interleave = 29 +}; + +const floppy_format_type FLOPPY_HPI_FORMAT = &floppy_image_format_creator<hpi_format>; diff --git a/src/lib/formats/hpi_dsk.h b/src/lib/formats/hpi_dsk.h new file mode 100644 index 00000000000..ded492cb74d --- /dev/null +++ b/src/lib/formats/hpi_dsk.h @@ -0,0 +1,55 @@ +// license:BSD-3-Clause +// copyright-holders: Ansgar Kückes, F. Ulivi +/********************************************************************* + + hpi_dsk.h + + "HPI" disk format + +*********************************************************************/ + +#pragma once + +#ifndef _HPI_DSK_H_ +#define _HPI_DSK_H_ + +#include "flopimg.h" + +// Geometry constants +constexpr unsigned HPI_TRACKS = 77; +constexpr unsigned HPI_HEADS = 2; +constexpr unsigned HPI_SECTORS = 30; +constexpr unsigned HPI_SECTOR_SIZE = 256; + +class hpi_format : public floppy_image_format_t +{ +public: + hpi_format(); + + virtual int identify(io_generic *io, uint32_t form_factor) override; + virtual bool load(io_generic *io, uint32_t form_factor, floppy_image *image) override; + virtual bool save(io_generic *io, floppy_image *image) override; + virtual const char *name() const override; + virtual const char *description() const override; + virtual const char *extensions() const override; + virtual bool supports_save() const override; + +private: + typedef std::array<uint8_t , HPI_SECTORS> sector_list_t; + static void interleaved_sectors(unsigned il_factor , sector_list_t& sector_list); + void write_mmfm_bit(std::vector<uint32_t> &buffer , bool data_bit , bool clock_bit); + void write_mmfm_byte(std::vector<uint32_t> &buffer , uint8_t data , uint8_t clock = 0); + void write_sync(std::vector<uint32_t> &buffer); + void write_crc(std::vector<uint32_t> &buffer , uint16_t crc); + void write_sector(std::vector<uint32_t> &buffer , uint8_t track_no , uint8_t sect_head_no , const uint8_t *sect_data); + void fill_with_gap3(std::vector<uint32_t> &buffer); + static unsigned chs_to_lba(unsigned cylinder , unsigned head , unsigned sector); + std::vector<uint8_t> get_next_id_n_block(const uint8_t *bitstream , int bitstream_size , int& pos , int& start_pos); + bool get_next_sector(const uint8_t *bitstream , int bitstream_size , int& pos , unsigned& track , unsigned& head , unsigned& sector , uint8_t *sector_data); + + static const uint8_t m_track_skew[ HPI_SECTORS - 1 ][ HPI_HEADS ]; +}; + +extern const floppy_format_type FLOPPY_HPI_FORMAT; + +#endif /* _HPI_DSK_H_ */ diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp index 190e2004ea6..a1a5f5a44d7 100644 --- a/src/tools/floptool.cpp +++ b/src/tools/floptool.cpp @@ -46,6 +46,8 @@ #include "formats/applix_dsk.h" +#include "formats/hpi_dsk.h" + static floppy_format_type floppy_formats[] = { FLOPPY_MFI_FORMAT, FLOPPY_DFI_FORMAT, @@ -75,6 +77,8 @@ static floppy_format_type floppy_formats[] = { FLOPPY_ORIC_DSK_FORMAT, FLOPPY_APPLIX_FORMAT, + + FLOPPY_HPI_FORMAT }; void CLIB_DECL ATTR_PRINTF(1,2) logerror(const char *format, ...) |