/* ".HEX" file output for gputils
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
James Bowman, Craig Franklin
This file is part of gputils.
gputils 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 2, or (at your option)
any later version.
gputils 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 gputils; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "stdhdr.h"
#include "libgputils.h"
/* mode flags */
#define all 0
#define low 1
#define high 2
#define swap 3 /* swap bytes for inhx16 format */
#define byte 4 /* write byte sized words */
static int sum;
static char *newline;
static FILE *hex;
MemBlock *memory;
static void new_record()
{
fprintf(hex, ":");
sum = 0;
}
static void write_byte(int b)
{
sum += b;
assert((0 <= b) && (b <= 255));
fprintf(hex, "%02X", b);
}
/* Write big-endian word */
static void write_bg_word(int w)
{
write_byte((w >> 8) & 0xff);
write_byte(w & 0xff);
}
/* Write little-endian word */
static void write_word(int w)
{
write_byte(w & 0xff);
write_byte((w >> 8) & 0xff);
}
static void end_record()
{
write_byte((-sum) & 0xff);
fprintf(hex, newline);
}
void data_line(int start, int stop, int mode)
{
new_record();
if (mode == all) {
write_byte(2 * (stop - start));
write_bg_word(2 * start);
write_byte(0);
while (start < stop){
write_word(i_memory_get(memory, start++));
}
} else if (mode == byte) {
write_byte(stop - start);
write_bg_word(start);
write_byte(0);
while (start < stop) {
write_byte((i_memory_get(memory, start++)) & 0xff);
}
} else if (mode == swap) {
write_byte(stop - start);
write_bg_word(start);
write_byte(0);
while (start < stop){
write_bg_word(i_memory_get(memory, start++));
}
} else {
write_byte(stop - start);
write_bg_word(start);
write_byte(0);
while (start < stop) {
if (mode == low) {
write_byte((i_memory_get(memory, start++)) & 0xff);
} else {
write_byte(((i_memory_get(memory, start++)) & 0xff00) >> 8);
}
}
}
end_record();
}
void seg_address_line(int segment)
{
new_record();
write_byte(2);
write_word(0);
write_byte(4);
write_bg_word(segment);
end_record();
}
void last_line()
{
new_record();
write_byte(0);
write_word(0);
write_byte(1);
end_record();
}
void write_i_mem(enum formats hex_format, int mode)
{
MemBlock *m = memory;
int i, j, maximum;
while(m) {
i = m->base << I_MEM_BITS;
maximum = i + MAX_I_MEM;
if (hex_format == inhx32) {
seg_address_line(m->base);
}
while (i < maximum) {
if ((i_memory_get(memory, i) & MEM_USED_MASK) == 0) {
++i;
} else {
j = i;
while ((i_memory_get(memory, i) & MEM_USED_MASK)) {
++i;
if (((mode == all) || (mode == swap)) && ((i & 0x7) == 0))
break;
if ((i & 0xf) == 0)
break;
}
/* Now we have a run of (i - j) occupied memory locations. */
/* Write the data to the file */
data_line(j, i, mode);
}
}
m = m->next;
}
last_line();
}
int writehex (char *basefilename,
MemBlock *m,
enum formats hex_format,
int numerrors,
int byte_words,
int dos_newlines)
{
char hexfilename[BUFSIZ];
char lowhex[BUFSIZ];
char highhex[BUFSIZ];
memory = m;
if (dos_newlines) {
newline = "\r\n";
} else {
newline = "\n";
}
/* build file names */
strncpy(hexfilename, basefilename, sizeof(hexfilename));
strncat(hexfilename, ".hex", sizeof(hexfilename));
strncpy(lowhex, basefilename, sizeof(lowhex));
strncat(lowhex, ".hxl", sizeof(lowhex));
strncpy(highhex, basefilename, sizeof(highhex));
strncat(highhex, ".hxh", sizeof(highhex));
if (numerrors) {
/* Remove the hex files (if any) */
unlink(hexfilename);
unlink(lowhex);
unlink(highhex);
return 0;
}
/* No error: overwrite the hex file */
if (hex_format == inhx8s) {
/* Write the low memory */
hex = fopen(lowhex, "wt");
if (hex == NULL) {
perror(lowhex);
exit(1);
}
write_i_mem(hex_format, low);
fclose(hex);
/* Write the high memory */
hex = fopen(highhex, "wt");
if (hex == NULL) {
perror(highhex);
exit(1);
}
write_i_mem(hex_format, high);
fclose(hex);
} else if (hex_format == inhx16) {
hex = fopen(hexfilename, "wt");
if (hex == NULL) {
perror(hexfilename);
exit(1);
}
write_i_mem(hex_format, swap);
fclose(hex);
} else {
hex = fopen(hexfilename, "wt");
if (hex == NULL) {
perror(hexfilename);
exit(1);
}
if (byte_words)
write_i_mem(hex_format, byte);
else
write_i_mem(hex_format, all);
fclose(hex);
}
return 0;
}
/* scan the memory to see if it exceeds 32K limit on inhx8m limit */
int check_writehex(MemBlock *m,
enum formats hex_format)
{
int error = 0;
if (hex_format == inhx8m) {
while(m) {
if (m->base > 0) {
error = 1;
}
m = m->next;
}
}
return error;
}
syntax highlighted by Code2HTML, v. 0.9.1