//
// srecord - manipulate eprom load files
// Copyright (C) 2000-2002, 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_wilson::srec_output_file_wilson() :
srec_output_file(),
pref_block_size(32)
{
}
srec_output_file_wilson::srec_output_file_wilson(
const std::string &a_file_name) :
srec_output_file(a_file_name),
pref_block_size(32)
{
}
srec_output_file_wilson::~srec_output_file_wilson()
{
// check for termination record
}
void
srec_output_file_wilson::put_byte(unsigned char n)
{
static const char *table[256] =
{
"@", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W",
"X", "Y", "Z", "[", "\\", "]", "^", "_",
"`", "a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w",
"x", "y", "z", "{", "|", "}", "~", "\177",
"\200", "\201", "\202", "\203", "\204", "\205", "\206", "\207",
"\210", "\211", "\212", "\213", "\214", "\215", "\216", "\217",
"\220", "\221", "\222", "\223", "\224", "\225", "\226", "\227",
"\230", "\231", "\232", "\233", "\234", "\235", "\236", "\237",
"\240", "\241", "\242", "\243", "\244", "\245", "\246", "\247",
"\250", "\251", "\252", "\253", "\254", "\255", "\256", "\257",
"\260", "\261", "\262", "\263", "\264", "\265", "\266", "\267",
"\270", "\271", "\272", "\273", "\274", "\275", "\276", "\277",
"\300", "\301", "\302", "\303", "\304", "\305", "\306", "\307",
"\310", "\311", "\312", "\313", "\314", "\315", "\316", "\317",
"\320", "\321", "\322", "\323", "\324", "\325", "\326", "\327",
"\330", "\331", "\332", "\333", "\334", "\335", "\336", "\337",
":0", ":1", ":2", ":3", ":4", ":5", ":6", ":7",
":8", ":9", "::", ":;", ":<", ":=", ":>", ":?",
";0", ";1", ";2", ";3", ";4", ";5", ";6", ";7",
";8", ";9", ";:", ";;", ";<", ";=", ";>", ";?",
"<0", "<1", "<2", "<3", "<4", "<5", "<6", "<7",
"<8", "<9", "<:", "<;", "<<", "<=", "<>", "",
"=0", "=1", "=2", "=3", "=4", "=5", "=6", "=7",
"=8", "=9", "=:", "=;", "=<", "==", "=>", "=?",
"\340", "\341", "\342", "\343", "\344", "\345", "\346", "\347",
"\350", "\351", "\352", "\353", "\354", "\355", "\356", "\357",
"\360", "\361", "\362", "\363", "\364", "\365", "\366", "\367",
"\370", "\371", "\372", "\373", "\374", "\375", "\376", "\377",
};
put_string(table[n]);
checksum_add(n);
}
void
srec_output_file_wilson::write_inner(int tag, unsigned long address,
const void *data, int data_nbytes)
{
//
// Make sure the line is not too long.
//
if (data_nbytes > 250)
fatal_error("data length (%d) too long", data_nbytes);
//
// Assemble the data for this line.
//
unsigned char buffer[256];
int line_length = data_nbytes + 5;
buffer[0] = line_length;
srec_record::encode_big_endian(buffer + 1, address, 4);
if (data_nbytes)
memcpy(buffer + 5, data, data_nbytes);
//
// Emit the line as hexadecimal text.
//
put_char(tag);
checksum_reset();
for (int j = 0; j < line_length; ++j)
put_byte(buffer[j]);
put_byte(~checksum_get());
put_char('\n');
}
void
srec_output_file_wilson::write(const srec_record &record)
{
switch (record.get_type())
{
case srec_record::type_header:
// This format doesn't appear to have header records
break;
case srec_record::type_data:
write_inner
(
'#',
record.get_address(),
record.get_data(),
record.get_length()
);
break;
case srec_record::type_data_count:
// ignore
break;
case srec_record::type_start_address:
if (data_only_flag)
break;
write_inner('\'', record.get_address(), 0, 0);
break;
case srec_record::type_unknown:
fatal_error("can't write unknown record type");
break;
}
}
void
srec_output_file_wilson::line_length_set(int linlen)
{
//
// Given the number of characters, figure the maximum number of
// data baytes.
// ...data...
// 1 + 2 + 8 + 2*n + 2 <= linlen
//
int n = (linlen - 15) / 2;
//
// Constrain based on the file format.
//
// The size field (max 255) includes the size of the data,
// the size of the address (4 bytes) and the size of the
// size (1 byte), thus 250 (255 - 4 - 1) bytes of data is
// the safest maximum.
//
if (n < 1)
n = 1;
else if (n > 250)
n = 250;
//
// An additional constraint is the size of the srec_record
// data buffer.
//
if (n > srec_record::max_data_length)
n = srec_record::max_data_length;
pref_block_size = n;
}
void
srec_output_file_wilson::address_length_set(int)
{
// ignore (this may change if I ever get a formal spec for
// this format)
}
int
srec_output_file_wilson::preferred_block_size_get()
const
{
return pref_block_size;
}
const char *
srec_output_file_wilson::mode()
const
{
return "wb";
}
const char *
srec_output_file_wilson::format_name()
const
{
return "Wilson";
}