From 1ca4a2a01201d1d02bf62fb6173e0ae05d0fa875 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 10 Sep 2016 17:01:17 -0400 Subject: [PATCH] =?UTF-8?q?Sought=20to=20be=20more=20intelligent=20in=20ha?= =?UTF-8?q?ndling=20cases=20where=20the=20two=20parts=20of=20a=20header=20?= =?UTF-8?q?or=20data=20field=20don't=20match=20=E2=80=94=20if=20either=20l?= =?UTF-8?q?ooks=20good=20then=20use=20it=20in=20isolation.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- StaticAnalyser/Commodore/Tape.cpp | 112 +++++++++++++++++++----------- 1 file changed, 70 insertions(+), 42 deletions(-) diff --git a/StaticAnalyser/Commodore/Tape.cpp b/StaticAnalyser/Commodore/Tape.cpp index 775a6e6f9..1cb9fe8ec 100644 --- a/StaticAnalyser/Commodore/Tape.cpp +++ b/StaticAnalyser/Commodore/Tape.cpp @@ -55,10 +55,74 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser get_next_header() + { + return duplicate_match
( + get_next_header_body(true), + get_next_header_body(false) + ); + } + + /*! + Advances to the next block on the tape, treating it as data, then consumes, parses, and returns it. + Returns @c nullptr if any wave-encoding level errors are encountered. + */ + std::unique_ptr get_next_data() + { + return duplicate_match( + get_next_data_body(true), + get_next_data_body(false) + ); + } + + void spin() + { + while(!is_at_end()) + { + SymbolType symbol = get_next_symbol(); + switch(symbol) + { + case SymbolType::One: printf("1"); break; + case SymbolType::Zero: printf("0"); break; + case SymbolType::Word: printf(" "); break; + case SymbolType::EndOfBlock: printf("\n"); break; + case SymbolType::LeadIn: printf("-"); break; + } + } + } + + private: + /*! + Template for the logic in selecting which of two copies of something to consider authoritative, + including setting the duplicate_matched flag. + */ + template + std::unique_ptr duplicate_match(std::unique_ptr first_copy, std::unique_ptr second_copy) + { + // if only one copy was parsed successfully, return it + if(!first_copy) return second_copy; + if(!second_copy) return first_copy; + + // if no copies were second_copy, return nullptr + if(!first_copy && !second_copy) return nullptr; + + // otherwise plan to return either one with a correct check digit, doing a comparison with the other + std::unique_ptr *copy_to_return = &first_copy; + if(!first_copy->parity_was_valid && second_copy->parity_was_valid) copy_to_return = &second_copy; + + (*copy_to_return)->duplicate_matched = true; + if(first_copy->data.size() != second_copy->data.size()) + (*copy_to_return)->duplicate_matched = false; + else + (*copy_to_return)->duplicate_matched = !(memcmp(&first_copy->data[0], &second_copy->data[0], first_copy->data.size())); + + return std::move(*copy_to_return); + } + + std::unique_ptr
get_next_header_body(bool is_original) { std::unique_ptr
header(new Header); reset_error_flag(); @@ -67,7 +131,7 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParserparity_was_valid = get_next_byte() == parity_byte; - // check that the duplicate matches - proceed_to_landing_zone(false); - header->duplicate_matched = true; - if(get_next_byte() != header_type) header->duplicate_matched = false; - for(size_t c = 0; c < 191; c++) - { - if(header->data[c] != get_next_byte()) header->duplicate_matched = false; - } - if(get_next_byte() != parity_byte) header->duplicate_matched = false; - // parse if this is not pure data if(header->type != Header::DataBlock) { @@ -119,14 +173,15 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser get_next_data() + + std::unique_ptr get_next_data_body(bool is_original) { std::unique_ptr data(new Data); reset_error_flag(); // find and proceed beyond lead-in tone to the next landing zone proceed_to_symbol(SymbolType::LeadIn); - proceed_to_landing_zone(true); + proceed_to_landing_zone(is_original); reset_parity_byte(); // accumulate until the next non-word marker is hit @@ -139,41 +194,14 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParserparity_was_valid = !get_parity_byte(); - - // compare to the duplicate - proceed_to_symbol(SymbolType::LeadIn); - proceed_to_landing_zone(false); - reset_parity_byte(); - data->duplicate_matched = true; - for(size_t c = 0; c < data->data.size(); c++) - { - if(get_next_byte() != data->data[c]) data->duplicate_matched = false; - } + data->duplicate_matched = false; // remove the captured parity data->data.erase(data->data.end()-1); - if(get_error_flag()) return nullptr; return data; } - void spin() - { - while(!is_at_end()) - { - SymbolType symbol = get_next_symbol(); - switch(symbol) - { - case SymbolType::One: printf("1"); break; - case SymbolType::Zero: printf("0"); break; - case SymbolType::Word: printf(" "); break; - case SymbolType::EndOfBlock: printf("\n"); break; - case SymbolType::LeadIn: printf("-"); break; - } - } - } - - private: /*! Finds and completes the next landing zone. */