avr: Fix documentation for Bus
[avr-sim.git] / src / HexProgram.cpp
blob116289642d9fd4d8901368c9cb4750325114bb7e
1 /*
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"
20 #include "Format.h"
21 #include "RuntimeException.h"
23 #include <string>
24 #include <iostream>
25 #include <memory.h>
27 namespace avr {
29 void HexProgram::load(const char *filename) {
30 if( f.is_open() )
31 f.close();
33 f.open( filename );
35 if( ! f.is_open() )
36 throw util::RuntimeException( util::format("Could not open file: %s") % filename );
38 end = false;
39 offset = 0;
42 HexProgram::~HexProgram() {
43 if( f.is_open() )
44 f.close();
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') )
56 return (hex - '0');
58 return -1;
61 static bool hex2bytes(const std::string & hex, size_t length,
62 unsigned char bytes[]) {
64 size_t off = 1;
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) )
69 return false;
71 bytes[i] = (valh << 4) | vall;
74 return true;
77 bool HexProgram::readNextSection(Section & s) {
78 if( end || f.eof() )
79 return false;
81 bool found = false;
82 do {
83 std::string line;
84 std::getline(f, line);
86 if( line[0] != ':' )
87 continue;
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)
95 crc += bytes[i];
97 if( crc != 0 ) {
98 std::cerr << "Invalid crc checksum" << std::endl;
99 continue;
102 const unsigned char rec_length = bytes[0];
103 if( length - 5 != rec_length ) {
104 std::cerr << "Invalid record length" << std::endl;
105 continue;
108 unsigned int addr = bytes[1] << 16 | bytes[2];
110 const unsigned char rec_type = bytes[3];
111 switch( rec_type ) {
112 case 0: // Data record
113 s.init(Section::FLASH, addr + offset, rec_length);
114 memcpy( s.data(), &bytes[4], rec_length );
115 found = true;
116 break;
118 case 1: // End-of-file record
119 end = true;
120 found = true;
121 break;
123 case 2: // Extended 8086 Segment Record
124 if( rec_length != 2 ) {
125 std::cerr << "Bad Extended 8086 Segment Record" << std::endl;
126 continue;
129 offset = (bytes[4]<<16 | bytes[5]) * 16;
130 break;
132 case 3: // Start Segment Address Record
133 break;
135 case 4: // Extended Linear Address Record
136 if( rec_length != 2 ) {
137 std::cerr << "Bad Extended Linear Address Record" << std::endl;
138 continue;
141 offset = (bytes[4]<<16 | bytes[5]) * 65536;
142 break;
144 case 5: // Start Linear Address Record
145 break;
148 } while( ! found && ! f.eof() );
150 return found;