diff options
Diffstat (limited to 'src/lib/formats/hti_tape.cpp')
-rw-r--r-- | src/lib/formats/hti_tape.cpp | 137 |
1 files changed, 74 insertions, 63 deletions
diff --git a/src/lib/formats/hti_tape.cpp b/src/lib/formats/hti_tape.cpp index f4a5727d591..7d6119860f1 100644 --- a/src/lib/formats/hti_tape.cpp +++ b/src/lib/formats/hti_tape.cpp @@ -11,6 +11,8 @@ #include "ioprocs.h" #include "multibyte.h" +#include <tuple> + static constexpr uint32_t OLD_FILE_MAGIC = 0x5441434f; // Magic value at start of old-format image file: "TACO" static constexpr uint32_t FILE_MAGIC_DELTA = 0x48544930; // Magic value at start of delta-modulation image file: "HTI0" @@ -54,10 +56,12 @@ bool hti_format_t::load_tape(util::random_read &io) return false; } - size_t actual; - uint8_t tmp[ 4 ]; + uint8_t tmp[4]; + auto const [err, actual] = read(io, tmp, 4); + if (err || (4 != actual)) { + return false; + } - io.read(tmp, 4, actual); auto magic = get_u32be(tmp); if (((m_img_format == HTI_DELTA_MOD_16_BITS || m_img_format == HTI_DELTA_MOD_17_BITS) && magic != FILE_MAGIC_DELTA && magic != OLD_FILE_MAGIC) || (m_img_format == HTI_MANCHESTER_MOD && magic != FILE_MAGIC_MANCHESTER)) { @@ -65,7 +69,7 @@ bool hti_format_t::load_tape(util::random_read &io) } for (unsigned i = 0; i < no_of_tracks(); i++) { - tape_track_t& track = m_tracks[ i ]; + tape_track_t &track = m_tracks[i]; if (!load_track(io, track, magic == OLD_FILE_MAGIC)) { clear_tape(); return false; @@ -77,17 +81,16 @@ bool hti_format_t::load_tape(util::random_read &io) void hti_format_t::save_tape(util::random_read_write &io) { - io.seek(0, SEEK_SET); + io.seek(0, SEEK_SET); // FIXME: check for errors - size_t actual; - uint8_t tmp[ 4 ]; + uint8_t tmp[4]; put_u32be(tmp, m_img_format == HTI_MANCHESTER_MOD ? FILE_MAGIC_MANCHESTER : FILE_MAGIC_DELTA); - io.write(tmp, 4, actual); + write(io, tmp, 4); // FIXME: check for errors for (unsigned i = 0; i < no_of_tracks(); i++) { - const tape_track_t& track = m_tracks[ i ]; - tape_pos_t next_pos = (tape_pos_t)-1; + const tape_track_t &track = m_tracks[i]; + tape_pos_t next_pos = tape_pos_t(-1); unsigned n_words = 0; tape_track_t::const_iterator it_start; for (tape_track_t::const_iterator it = track.cbegin(); it != track.cend(); ++it) { @@ -102,20 +105,20 @@ void hti_format_t::save_tape(util::random_read_write &io) dump_sequence(io, it_start, n_words); // End of track put_u32le(tmp, (uint32_t)-1); - io.write(tmp, 4, actual); + write(io, tmp, 4); // FIXME: check for errors } } void hti_format_t::clear_tape() { - for (tape_track_t& track : m_tracks) { + for (tape_track_t &track : m_tracks) { track.clear(); } } hti_format_t::tape_pos_t hti_format_t::word_length(tape_word_t w) const { - unsigned zeros , ones; + unsigned zeros, ones; // pop count of w ones = (w & 0x5555) + ((w >> 1) & 0x5555); @@ -128,7 +131,7 @@ hti_format_t::tape_pos_t hti_format_t::word_length(tape_word_t w) const return zeros * bit_length(false) + ones * bit_length(true); } -hti_format_t::tape_pos_t hti_format_t::farthest_end(const track_iterator_t& it , bool forward) const +hti_format_t::tape_pos_t hti_format_t::farthest_end(const track_iterator_t &it, bool forward) const { if (forward) { return word_end_pos(it); @@ -137,7 +140,7 @@ hti_format_t::tape_pos_t hti_format_t::farthest_end(const track_iterator_t& it , } } -bool hti_format_t::pos_offset(tape_pos_t& pos , bool forward , tape_pos_t offset) +bool hti_format_t::pos_offset(tape_pos_t &pos, bool forward, tape_pos_t offset) { if (offset == 0) { return true; @@ -161,7 +164,7 @@ bool hti_format_t::pos_offset(tape_pos_t& pos , bool forward , tape_pos_t offset } } -hti_format_t::tape_pos_t hti_format_t::next_hole(tape_pos_t pos , bool forward) +hti_format_t::tape_pos_t hti_format_t::next_hole(tape_pos_t pos, bool forward) { if (forward) { for (tape_pos_t hole : tape_holes) { @@ -172,9 +175,9 @@ hti_format_t::tape_pos_t hti_format_t::next_hole(tape_pos_t pos , bool forward) // No more holes: will hit end of tape return NULL_TAPE_POS; } else { - for (int i = (sizeof(tape_holes) / sizeof(tape_holes[ 0 ])) - 1; i >= 0; i--) { - if (tape_holes[ i ] < pos) { - return tape_holes[ i ]; + for (int i = (sizeof(tape_holes) / sizeof(tape_holes[0])) - 1; i >= 0; i--) { + if (tape_holes[i] < pos) { + return tape_holes[i]; } } // No more holes: will hit start of tape @@ -182,16 +185,16 @@ hti_format_t::tape_pos_t hti_format_t::next_hole(tape_pos_t pos , bool forward) } } -void hti_format_t::write_word(unsigned track_no , tape_pos_t start , tape_word_t word , tape_pos_t& length , bool forward) +void hti_format_t::write_word(unsigned track_no, tape_pos_t start, tape_word_t word, tape_pos_t &length, bool forward) { - tape_track_t& track = m_tracks[ track_no ]; + tape_track_t &track = m_tracks[track_no]; track_iterator_t it_low = track.lower_bound(start); - adjust_it(track , it_low , start); + adjust_it(track, it_low, start); length = word_length(word); tape_pos_t end_pos = start + length; track_iterator_t it_high = track.lower_bound(end_pos); - track.erase(it_low , it_high); + track.erase(it_low, it_high); // A 0 word is inserted after the word being written, if space allows. // This is meant to avoid fragmentation of the slack space at the end of a record @@ -203,24 +206,24 @@ void hti_format_t::write_word(unsigned track_no , tape_pos_t start , tape_word_t it_high--; } - track.insert(it_high , std::make_pair(start, word)); + track.insert(it_high, std::make_pair(start, word)); } -void hti_format_t::write_gap(unsigned track_no , tape_pos_t a , tape_pos_t b) +void hti_format_t::write_gap(unsigned track_no, tape_pos_t a, tape_pos_t b) { - ensure_a_lt_b(a , b); - tape_track_t& track = m_tracks[ track_no ]; + ensure_a_lt_b(a, b); + tape_track_t &track = m_tracks[track_no]; track_iterator_t it_low = track.lower_bound(a); - adjust_it(track , it_low , a); + adjust_it(track, it_low, a); track_iterator_t it_high = track.lower_bound(b); track.erase(it_low, it_high); } -bool hti_format_t::just_gap(unsigned track_no , tape_pos_t a , tape_pos_t b) +bool hti_format_t::just_gap(unsigned track_no, tape_pos_t a, tape_pos_t b) { - ensure_a_lt_b(a , b); - tape_track_t& track = m_tracks[ track_no ]; + ensure_a_lt_b(a, b); + tape_track_t &track = m_tracks[track_no]; track_iterator_t it_low = track.lower_bound(a); track_iterator_t it_high = track.lower_bound(b); @@ -229,9 +232,9 @@ bool hti_format_t::just_gap(unsigned track_no , tape_pos_t a , tape_pos_t b) return it_low == it_high; } -bool hti_format_t::next_data(unsigned track_no , tape_pos_t pos , bool forward , bool inclusive , track_iterator_t& it) +bool hti_format_t::next_data(unsigned track_no, tape_pos_t pos, bool forward, bool inclusive, track_iterator_t &it) { - tape_track_t& track = m_tracks[ track_no ]; + tape_track_t &track = m_tracks[track_no]; it = track.lower_bound(pos); if (forward) { if (inclusive) { @@ -251,9 +254,9 @@ bool hti_format_t::next_data(unsigned track_no , tape_pos_t pos , bool forward , } } -hti_format_t::adv_res_t hti_format_t::adv_it(unsigned track_no , bool forward , track_iterator_t& it) +hti_format_t::adv_res_t hti_format_t::adv_it(unsigned track_no, bool forward, track_iterator_t &it) { - tape_track_t& track = m_tracks[ track_no ]; + tape_track_t &track = m_tracks[track_no]; if (forward) { tape_pos_t prev_pos = word_end_pos(it); ++it; @@ -275,7 +278,7 @@ hti_format_t::adv_res_t hti_format_t::adv_it(unsigned track_no , bool forward , } } -bool hti_format_t::sync_with_record(unsigned track_no , track_iterator_t& it , unsigned& bit_idx) +bool hti_format_t::sync_with_record(unsigned track_no, track_iterator_t &it, unsigned &bit_idx) { while ((it->second & (1U << bit_idx)) == 0) { if (bit_idx) { @@ -296,7 +299,7 @@ bool hti_format_t::sync_with_record(unsigned track_no , track_iterator_t& it , u return true; } -hti_format_t::adv_res_t hti_format_t::next_word(unsigned track_no , track_iterator_t& it , unsigned& bit_idx , tape_word_t& word) +hti_format_t::adv_res_t hti_format_t::next_word(unsigned track_no, track_iterator_t &it, unsigned &bit_idx, tape_word_t &word) { if (bit_idx == 15) { auto res = adv_it(track_no, true, it); @@ -319,13 +322,13 @@ hti_format_t::adv_res_t hti_format_t::next_word(unsigned track_no , track_iterat } } -bool hti_format_t::next_gap(unsigned track_no , tape_pos_t& pos , bool forward , tape_pos_t min_gap) +bool hti_format_t::next_gap(unsigned track_no, tape_pos_t &pos, bool forward, tape_pos_t min_gap) { tape_track_t::iterator it; // First align with next data - next_data(track_no , pos , forward , true , it); + next_data(track_no, pos, forward, true, it); // Then scan for 1st gap - tape_track_t& track = m_tracks[ track_no ]; + tape_track_t &track = m_tracks[track_no]; bool done = false; track_iterator_t prev_it; unsigned n_gaps = 1; @@ -346,7 +349,7 @@ bool hti_format_t::next_gap(unsigned track_no , tape_pos_t& pos , bool forward , adv_res_t adv_res; do { prev_it = it; - adv_res = adv_it(track_no , forward , it); + adv_res = adv_it(track_no, forward, it); } while (adv_res == ADV_CONT_DATA); pos = word_end_pos(prev_it); } @@ -366,32 +369,36 @@ bool hti_format_t::next_gap(unsigned track_no , tape_pos_t& pos , bool forward , adv_res_t adv_res; do { prev_it = it; - adv_res = adv_it(track_no , forward , it); + adv_res = adv_it(track_no, forward, it); } while (adv_res == ADV_CONT_DATA); pos = prev_it->first; } } // Set "pos" where minimum gap size is met - pos_offset(pos , forward , min_gap); + pos_offset(pos, forward, min_gap); return n_gaps == 0; } -bool hti_format_t::load_track(util::random_read &io , tape_track_t& track , bool old_format) +bool hti_format_t::load_track(util::random_read &io, tape_track_t &track, bool old_format) { - size_t actual; - uint8_t tmp[ 4 ]; - uint32_t tmp32; tape_pos_t delta_pos = 0; tape_pos_t last_word_end = 0; track.clear(); while (1) { - // Read no. of words to follow - io.read(tmp, 4, actual); + std::error_condition err; + size_t actual; + uint8_t tmp[4]; + uint32_t tmp32; + // Read no. of words to follow + std::tie(err, actual) = read(io, tmp, 4); + if (err || (4 != actual)) { + return false; + } tmp32 = get_u32le(tmp); // Track ends @@ -402,8 +409,10 @@ bool hti_format_t::load_track(util::random_read &io , tape_track_t& track , bool unsigned n_words = tmp32; // Read tape position of block - io.read(tmp, 4, actual); - + std::tie(err, actual) = read(io, tmp, 4); + if (err || (4 != actual)) { + return false; + } tmp32 = get_u32le(tmp); tape_pos_t pos = (tape_pos_t)tmp32 + delta_pos; @@ -414,11 +423,14 @@ bool hti_format_t::load_track(util::random_read &io , tape_track_t& track , bool for (unsigned i = 0; i < n_words; i++) { uint16_t tmp16; - io.read(tmp, 2, actual); + std::tie(err, actual) = read(io, tmp, 2); + if (err || (2 != actual)) { + return false; + } tmp16 = get_u16le(tmp); if (!old_format) { - track.insert(std::make_pair(pos , tmp16)); + track.insert(std::make_pair(pos, tmp16)); pos += word_length(tmp16); } else if (m_img_format == HTI_DELTA_MOD_16_BITS) { // Convert HP9845 & HP85 old format @@ -471,29 +483,28 @@ bool hti_format_t::load_track(util::random_read &io , tape_track_t& track , bool } } -void hti_format_t::dump_sequence(util::random_read_write &io , tape_track_t::const_iterator it_start , unsigned n_words) +void hti_format_t::dump_sequence(util::random_read_write &io, tape_track_t::const_iterator it_start, unsigned n_words) { if (n_words) { - size_t actual; - uint8_t tmp[ 8 ]; - put_u32le(&tmp[ 0 ], n_words); - put_u32le(&tmp[ 4 ], it_start->first); - io.write(tmp, 8, actual); + uint8_t tmp[8]; + put_u32le(&tmp[0], n_words); + put_u32le(&tmp[4], it_start->first); + write(io, tmp, 8); // FIXME: check for errors for (unsigned i = 0; i < n_words; i++) { put_u16le(tmp, it_start->second); - io.write(tmp, 2, actual); + write(io, tmp, 2); // FIXME: check for errors ++it_start; } } } -hti_format_t::tape_pos_t hti_format_t::word_end_pos(const track_iterator_t& it) const +hti_format_t::tape_pos_t hti_format_t::word_end_pos(const track_iterator_t &it) const { return it->first + word_length(it->second); } -void hti_format_t::adjust_it(tape_track_t& track , track_iterator_t& it , tape_pos_t pos) const +void hti_format_t::adjust_it(tape_track_t &track, track_iterator_t &it, tape_pos_t pos) const { if (it != track.begin()) { --it; @@ -503,7 +514,7 @@ void hti_format_t::adjust_it(tape_track_t& track , track_iterator_t& it , tape_p } } -void hti_format_t::ensure_a_lt_b(tape_pos_t& a , tape_pos_t& b) +void hti_format_t::ensure_a_lt_b(tape_pos_t &a, tape_pos_t &b) { if (a > b) { // Ensure A always comes before B |