// // srecord - manipulate eprom load files // Copyright (C) 2004, 2006, 2007 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // . // #include #include srec_output_file_stewie::srec_output_file_stewie( const std::string &a_file_name) : srec_output_file(a_file_name), data_count(0), address_length(2), preferred_block_size(128) { } srec_output_file_stewie::~srec_output_file_stewie() { } void srec_output_file_stewie::put_byte(unsigned char n) { put_char(n); checksum_add(n); } void srec_output_file_stewie::write_inner(int tag, unsigned long address, int address_nbytes, const void *data, int data_nbytes) { // // Make sure the record is not too long. // if (address_nbytes + data_nbytes > 254) { fatal_error ( "data length (%d+%d) too long", address_nbytes, data_nbytes ); } // // Assemble the data for this record. // unsigned char buffer[256]; int line_length = address_nbytes + data_nbytes + 1; buffer[0] = line_length; srec_record::encode_big_endian(buffer + 1, address, address_nbytes); if (data_nbytes) memcpy(buffer + 1 + address_nbytes, data, data_nbytes); // // Emit the record as binary data. // put_char('S'); put_nibble(tag); switch (tag) { case 0: put_char('0'); put_char('3'); break; case 7: case 8: case 9: break; default: checksum_reset(); for (int j = 0; j < line_length; ++j) put_byte(buffer[j]); put_byte(~checksum_get()); break; } } void srec_output_file_stewie::write(const srec_record &record) { switch (record.get_type()) { case srec_record::type_header: if (data_only_flag) break; // // Even though it starts with S0, the header record has a fixed // format, so we don't bother passing it any data. // write_inner(0, 0, 0, 0, 0); break; case srec_record::type_data: if ( record.get_address() < (1UL << 16) && address_length <= 2 ) { write_inner ( 1, record.get_address(), 2, record.get_data(), record.get_length() ); } else if ( record.get_address() < (1UL << 24) && address_length <= 3 ) { write_inner ( 2, record.get_address(), 3, record.get_data(), record.get_length() ); } else { write_inner ( 3, record.get_address(), 4, record.get_data(), record.get_length() ); } ++data_count; break; case srec_record::type_data_count: // ignore break; case srec_record::type_start_address: if (data_only_flag) break; // // Even though struct Motorola compatibility would seem to // indicate the S7, S8 or S9 could terminate the file, only S8 // seems to work. // write_inner(8, 0, 0, 0, 0); break; case srec_record::type_unknown: fatal_error("can't write unknown record type"); } } void srec_output_file_stewie::line_length_set(int n) { if (n < 1) n = 1; else if (n > 250) n = 250; preferred_block_size = n; } void srec_output_file_stewie::address_length_set(int n) { if (n < 2) n = 2; else if (n > 4) n = 4; address_length = n; } int srec_output_file_stewie::preferred_block_size_get() const { return preferred_block_size; } const char * srec_output_file_stewie::mode() const { return "wb"; } const char * srec_output_file_stewie::format_name() const { return "Stewie"; }