2 * avr-sim: An atmel AVR simulator
3 * Copyright (C) 2008 Tom Haber
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "HexProgram.h"
21 #include "RuntimeException.h"
29 void HexProgram::load(const char *filename
) {
36 throw util::RuntimeException( util::format("Could not open file: %s") % filename
);
42 HexProgram::~HexProgram() {
47 /* Convert a hexidecimal digit to a 4 bit nibble. */
48 static int hex2nib( char hex
) {
49 if( (hex
>= 'A') && (hex
<= 'F') )
50 return (10 + (hex
- 'A'));
52 else if( (hex
>= 'a') && (hex
<= 'f') )
53 return (10 + (hex
- 'a'));
55 else if( (hex
>= '0') && (hex
<= '9') )
61 static bool hex2bytes(const std::string
& hex
, size_t length
,
62 unsigned char bytes
[]) {
65 for(size_t i
= 0; i
< length
; ++i
) {
66 int valh
= hex2nib( hex
[off
++] );
67 int vall
= hex2nib( hex
[off
++] );
68 if( (valh
== -1) && (vall
== -1) )
71 bytes
[i
] = (valh
<< 4) | vall
;
77 bool HexProgram::readNextSection(Section
& s
) {
84 std::getline(f
, line
);
89 size_t length
= (line
.size() - 1) / 2;
90 unsigned char bytes
[length
];
91 hex2bytes(line
, length
, bytes
);
93 unsigned char crc
= 0;
94 for(size_t i
= 0; i
< length
; ++i
)
98 std::cerr
<< "Invalid crc checksum" << std::endl
;
102 const unsigned char rec_length
= bytes
[0];
103 if( length
- 5 != rec_length
) {
104 std::cerr
<< "Invalid record length" << std::endl
;
108 unsigned int addr
= bytes
[1] << 16 | bytes
[2];
110 const unsigned char rec_type
= bytes
[3];
112 case 0: // Data record
113 s
.init(Section::FLASH
, addr
+ offset
, rec_length
);
114 memcpy( s
.data(), &bytes
[4], rec_length
);
118 case 1: // End-of-file record
123 case 2: // Extended 8086 Segment Record
124 if( rec_length
!= 2 ) {
125 std::cerr
<< "Bad Extended 8086 Segment Record" << std::endl
;
129 offset
= (bytes
[4]<<16 | bytes
[5]) * 16;
132 case 3: // Start Segment Address Record
135 case 4: // Extended Linear Address Record
136 if( rec_length
!= 2 ) {
137 std::cerr
<< "Bad Extended Linear Address Record" << std::endl
;
141 offset
= (bytes
[4]<<16 | bytes
[5]) * 65536;
144 case 5: // Start Linear Address Record
148 } while( ! found
&& ! f
.eof() );