Removed dependency of Cygwin from hexameter.

This commit is contained in:
matsutsuka 2008-07-20 07:44:39 +00:00
parent f822ac9797
commit 6c9291f38b
23 changed files with 440 additions and 182 deletions

View file

@ -2,7 +2,7 @@
# Makefile for PC-6001 using z80/SDCC # Makefile for PC-6001 using z80/SDCC
# @author Takahide Matsutsuka <markn@markn.org> # @author Takahide Matsutsuka <markn@markn.org>
# #
# $Id: Makefile.pc-6001,v 1.9 2008/07/02 15:04:07 matsutsuka Exp $ # $Id: Makefile.pc-6001,v 1.10 2008/07/20 07:44:39 matsutsuka Exp $
# #
ifndef CONTIKI ifndef CONTIKI
@ -48,7 +48,8 @@ endif
### setup default values ### setup default values
ifndef HEX2BIN ifndef HEX2BIN
HEX2BIN = ../../tools/z80/hex2bin/hexameter HEX2BINDIR = ../../tools/z80/hex2bin/
HEX2BIN = $(HEX2BINDIR)/hexameter
endif endif
### setup flags to be used in compiler, assembler, and HEX2BIN ### setup flags to be used in compiler, assembler, and HEX2BIN
@ -59,16 +60,16 @@ CFLAGS += -DMEMORY_$(MEMORY) -DARCH_$(ARCH) -DCTK_$(CTKCONF)
ifeq ($(MEMORY),16K) ifeq ($(MEMORY),16K)
LDFLAGS += --code-loc 0xc40f --data-loc 0 LDFLAGS += --code-loc 0xc40f --data-loc 0
HEX2BINFLAGS = -p mode1 -s suffix -o contiki.p6 HEX2BINFLAGS = -d TAPE=contki $(HEX2BINDIR)/ihx/mode1.ihx -o contiki.p6
else ifeq ($(MEMORY),ROM) else ifeq ($(MEMORY),ROM)
LDFLAGS += --code-loc 0x4004 --data-loc 0xf000 LDFLAGS += --code-loc 0x4004 --data-loc 0xf000
HEX2BINFLAGS = -p rom60 -o contiki.rom HEX2BINFLAGS = -d ROMEXEC=4004 $(HEX2BINDIR)/ihx/rom60.ihx -b 4000 -o contiki.rom
else ifeq ($(ARCH),PC6001MK2) else ifeq ($(ARCH),PC6001MK2)
LDFLAGS += --code-loc 0x800f --data-loc 0 LDFLAGS += --code-loc 0x800f --data-loc 0
HEX2BINFLAGS = -p mode5 -s suffix -o contiki2.p6 HEX2BINFLAGS = -d TAPE=contki $(HEX2BINDIR)/ihx/mode5.ihx -o contiki2.p6
else else
LDFLAGS += --code-loc 0x840f --data-loc 0 LDFLAGS += --code-loc 0x840f --data-loc 0
HEX2BINFLAGS = -p mode2 -s suffix -o contiki.p6 HEX2BINFLAGS = -d TAPE=contki $(HEX2BINDIR)/ihx/mode2.ihx -o contiki.p6
endif endif
ifeq ($(LOADER),1) ifeq ($(LOADER),1)
@ -108,12 +109,12 @@ contiki: $(HEX2BIN) contiki.p6
.SUFFIXES: .SUFFIXES:
%.p6: %.ihx %.p6: %.ihx
$(HEX2BIN) $(HEX2BINFLAGS) $< $(HEX2BIN) $(HEX2BINFLAGS) $< $(HEX2BINDIR)/ihx/suffix.ihx
%.rom: %.ihx %.rom: %.ihx
$(HEX2BIN) $(HEX2BIN) $(HEX2BINFLAGS) $< $(HEX2BIN) $(HEX2BINFLAGS) $<
$(HEX2BIN): $(HEX2BIN):
cd ../../tools/z80/hex2bin/; make cd $(HEX2BINDIR); make
remove-ctk: remove-ctk:
rm -f obj_$(TARGET)/ctk*; rm -f obj_$(TARGET)/ctk*;

View file

@ -27,7 +27,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: contiki-main.c,v 1.2 2008/07/02 15:03:44 matsutsuka Exp $ * $Id: contiki-main.c,v 1.3 2008/07/20 07:44:39 matsutsuka Exp $
* *
*/ */
@ -71,7 +71,7 @@ main(void)
#else #else
program_handler_add(&processes_dsc, "Processes", 1); program_handler_add(&processes_dsc, "Processes", 1);
program_handler_add(&mttest_dsc, "Multithread", 1); program_handler_add(&mttest_dsc, "Multithread", 1);
// program_handler_add(&calc_dsc, "Calculator", 1); program_handler_add(&calc_dsc, "Calculator", 1);
program_handler_add(&about_dsc, "About", 1); program_handler_add(&about_dsc, "About", 1);
// program_handler_add(&shell_dsc, "Command shell", 1); // program_handler_add(&shell_dsc, "Command shell", 1);
#endif #endif

View file

@ -0,0 +1,26 @@
Copyright (c) 2008, Takahide Matsutsuka.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the author nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

View file

@ -2,16 +2,30 @@
# Makefile for hexameter # Makefile for hexameter
# @author Takahide Matsutsuka <markn@markn.org> # @author Takahide Matsutsuka <markn@markn.org>
# #
# $Id: Makefile,v 1.1 2008/07/02 07:17:14 matsutsuka Exp $ # $Id: Makefile,v 1.2 2008/07/20 07:44:39 matsutsuka Exp $
# #
CFLAGS = CFLAGS = -std=c99 -g -mno-cygwin -Wall
SOURCEDIR = src #CFLAGS = -std=c99 -g -Wall
TARGET = hexameter.o ihx2bin.o SOURCEDIR = src
SOURCES = hexameter.c ihx2bin.c
OBJECTDIR = bin
OBJECTS = ${addprefix $(OBJECTDIR)/,$(SOURCES:.c=.o)}
vpath %.c $(SOURCEDIR) vpath %.c $(SOURCEDIR)
hexameter: $(TARGET) ifeq (${wildcard $(OBJECTDIR)},)
DUMMY := ${shell mkdir $(OBJECTDIR)}
endif
hexameter: $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $(OBJECTS)
clean: clean:
rm -f *.o *~ hexameter.exe rm -rf bin
rm -f *~ *.stackdump
rm -f *~ hexameter.exe
$(OBJECTDIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

View file

@ -1,5 +1,5 @@
hexameter : Convert Intel hex files to a binary file hexameter : Convert Intel hex files to a binary file
version 2.0.0 version 2.1.0
Copyright (c) 2003-2008, Takahide Matsutsuka. Copyright (c) 2003-2008, Takahide Matsutsuka.
1/ What is it? 1/ What is it?
@ -13,15 +13,15 @@ other old computers.
2/ Installation 2/ Installation
Installation can be done in following steps. Installation can be done in the following steps.
a) Download and install SDCC from http://sdcc.sf.net/ a) Download and install SDCC from http://sdcc.sf.net/
Version 2.8.0 is tested. Version 2.8.0 has been tested.
SDCC is a cross-compiler for Z80 and other 8bit CPUs. SDCC is a cross-compiler for Z80 and other 8bit CPUs.
Extract an archive on your disk, say "c:/sdcc". Extract an archive on your disk, say "c:/sdcc".
b) Copy hexameter.exe to any path-available directory. for exmaple b) Place hexameter.exe and prefix/suffix files to any path-available
"c:/sdcc/bin". directory.
3/ Use 3/ Use
@ -60,38 +60,30 @@ b) Compile your code using SDCC.
c) Convert ihx file to cas file using hex2cas. c) Convert ihx file to cas file using hex2cas.
hexameter YOUR_CODE.ihx [YOUR_CODE2.ihx ...] hexameter <ihx_file|binary_file> [ihx_file|binary_file ...]
The ihx files are just attached in the specified order. The ihx files are just attached in the specified order.
Here you can take some options: Here you can take some options:
-p <filename> specify prefix file name. -o <filename> specify output file name
-s <filename> specify suffix file name. -d <name>=<value> define ihx-specific value replacement
-n <name> specify PC-6001 cassette file name, -v verbose output
must be 6 characters or less. -b <size> size of the output file in hexadecimal bytes.
-v verbose output only if the size of the output is less than the size
-o <filename> specify output file name specified, the trailing bytes will filled by zeroes.
-b <size> size of the output file in hexadecimal bytes. note that it doesn't mean the size of output is
only if the size of the output is less than the size restricted by the given size.
specified, the trailing bytes will filled by zeroes. -h displays simple usage
note that it doesn't mean the size of output is
restricted by the given size.
-h displays simple usage
Prefixes and suffixes are provided by files, which should be in the same You can find various predefined library file in "lib" directory.
directory as hexameter.exe. Each of them may take its own optional value, which you can specify
mode1 with -d option.
mode2
mode5
n88
rom60
rom62
suffix
d) Example d) Example
The following is a typical example to convert from ihx files to The following is a typical example to convert from ihx files to
PC-6001 loadable cassette format. PC-6001 loadable cassette format.
% hexameter -p mode2 -s suffix mycode1.ihx mycode2.ihx -o myapp.p6 % hexameter -v TAPE=myfile mode2.ihx mycode2.ihx -o myapp.p6
Note that TAPE value is defined in mode2.ihx, defines cassette file name.
e) Load your cas file into your 6001 emulator. e) Load your cas file into your 6001 emulator.
@ -105,15 +97,52 @@ e) Load your cas file into your 6001 emulator.
http://bernie.hp.infoseek.co.jp/develop/pc6001vw.html http://bernie.hp.infoseek.co.jp/develop/pc6001vw.html
4/ Note 4/ IHX extentions
- While I've tested the tool on Cigwin on Win32, I think it works To support run-time user specified values in ihx files, Hexameter supports
on other environments with a little work. extended ihx files. Examples are located in ihx directory.
For example, mode2.ihx has the following line.
:06000a02TAPE
As in normal ihx format, the first 9 characters conform to the following
format:
:AABBBBCC
AA bytes encoded in this line
BBBB start address of this line
CC type of this line
The normal ihx file, which sdcc emits, has the type 00 (data) and 01 (end of
file). In addition to this, Hexameter supports the following types.
02 string
03 byte
04 word (encoded in little endian)
The rest of line defines a name of the definition. In the example above,
the name TAPE is assigned to this line. You can use latin alphabets,
numbers, and underscore (_) for the name. Letters are case-sensitive.
When you run Hexameter, you can specify a value for this definition like:
hexameter -d TAPE=xxxx
Since this example defines 06 in the bytes field, TAPE can have up to
six characters. This string will override the memory location 000a
specified in the second field.
For type 03 (byte) and 04 (word), bytes field has no effect.
5/ Note
- Cygwin dependency has been removed.
- SDCC has many isuues regarding compilation. Don't blame me about them! :) - SDCC has many isuues regarding compilation. Don't blame me about them! :)
5/ History 6/ History
3/29/2003 1.0.0 First version 3/29/2003 1.0.0 First version
4/20/2003 1.0.1 Mode option has been added 4/20/2003 1.0.1 Mode option has been added
@ -123,6 +152,8 @@ e) Load your cas file into your 6001 emulator.
4/28/2008 1.4.0 Header file option introduced 4/28/2008 1.4.0 Header file option introduced
5/17/2008 2.0.0 Migrated to hexameter, to support more flexible configurations 5/17/2008 2.0.0 Migrated to hexameter, to support more flexible configurations
7/16/2008 2.1.0 Support arguments in ihx file, remove prefix/suffix instead
7/18/2008 2.1.1 Cygwin dependency has been removed
Enjoy! Enjoy!

View file

@ -0,0 +1,3 @@
:10000000d3d3d3d3d3d3d3d3d3d3000000000000
:0e0010000dc40a00a5264843343046000000
:06000a02TAPE

View file

@ -0,0 +1,3 @@
:10000000d3d3d3d3d3d3d3d3d3d3000000000000
:0e0010000d840a00a5264838343046000000
:06000a02TAPE

View file

@ -0,0 +1,3 @@
:10000000d3d3d3d3d3d3d3d3d3d3000000000000
:0e0010000d800a00a5264838303046000000
:06000a02TAPE

View file

@ -0,0 +1,3 @@
:10000000544d6767676767676767000000000000
:02000c04MP6LOAD
:02000e04MP6EXEC

View file

@ -0,0 +1,18 @@
:10000000d3d3d3d3d3d3d3d3d3d3202020202020
:100010000d000a009720e0f10c00010018001400
:1000200041f1e028112900000020202020202020
:1000300020202020202020202020202020202020
:1000400020202020202020202020202020202020
:1000500020202020202020202020202020202020
:1000600020202020202020202020202020202020
:1000700020202020202020202020202020202020
:1000800020202020202020202020202020202020
:1000900020202020202020202020202020202020
:1000a00020202020202020202020202020202020
:1000b00020202020202020202020202020202020
:1000c00020202020202020202020202020202020
:1000d00020202020202020202020202020202020
:1000e00020202020202020202020202020202020
:1000f00020202020202020202020202020202020
:0f010000202020202020202020202020202020
:06000a02TAPE

View file

@ -0,0 +1,2 @@
:0400000041420440
:02000204ROMEXEC

View file

@ -0,0 +1,2 @@
:0400000043440440
:02000204ROMEXEC

View file

@ -0,0 +1 @@
:0c000000000000000000000000000000

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1 +0,0 @@
AB@

View file

@ -1 +0,0 @@
CD@

View file

@ -38,29 +38,24 @@
* A main file for hex2cas. * A main file for hex2cas.
*/ */
#define MAX_PATH 1024
#if __CYGWIN32__
#include <windows.h>
#else
#include <stdlib.h>
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#ifndef TRUE #include <ctype.h>
#define TRUE 1
#endif
#include "ihx2bin.h" #include "ihx2bin.h"
#define MAXFILES 256 #define MAXFILES 256
struct Configuration { typedef struct {
char* output; char* output;
char* prefix;
char* suffix;
char* dir; char* dir;
char archname[6];
char *files[MAXFILES]; char *files[MAXFILES];
unsigned int defsize;
struct ConvertDefinition defs[DEF_MAX];
unsigned char verbose; unsigned char verbose;
// number of the ihx files // number of the ihx files
int length; int length;
@ -68,9 +63,33 @@ struct Configuration {
int size; int size;
// output file wriiten size // output file wriiten size
int written; int written;
}; } Configuration;
static char *changeExt(const char *path, const char* ext) { static
const char* IHXEXT = ".ihx";
static
const char *strcasestr(const char *haystack, const char *needle) {
int haypos;
int needlepos;
haypos = 0;
while (haystack[haypos]) {
if (tolower (haystack[haypos]) == tolower(needle[0])) {
needlepos = 1;
while ( (needle[needlepos]) &&
(tolower(haystack[haypos + needlepos])
== tolower(needle[needlepos])) )
++needlepos;
if (! needle[needlepos]) return (haystack + haypos);
}
++haypos;
}
return NULL;
}
static
char *changeExt(const char *path, const char* ext) {
char *p; char *p;
char *tail; char *tail;
char *changed; char *changed;
@ -79,7 +98,6 @@ static char *changeExt(const char *path, const char* ext) {
for (tail = (char*) path; *tail != 0; tail++); for (tail = (char*) path; *tail != 0; tail++);
for (p = tail; p > path; p--) { for (p = tail; p > path; p--) {
if (*p == '.') { if (*p == '.') {
len = p - path; len = p - path;
changed = (char*) malloc(len + extlen + 2); changed = (char*) malloc(len + extlen + 2);
@ -98,47 +116,50 @@ static char *changeExt(const char *path, const char* ext) {
return changed; return changed;
} }
static unsigned char analyzeOption(int argc, char **argv, struct Configuration *config) { static
unsigned char analyzeOption(int argc, char **argv, Configuration *config) {
int c; int c;
char *defval;
opterr = 0; opterr = 0;
while ((c = getopt(argc, argv, "hvo:p:s:n:b:")) != EOF) { while ((c = getopt(argc, argv, "hvo:d:b:")) != EOF) {
int i;
switch (c) { switch (c) {
case 'v': case 'v':
config->verbose = TRUE; config->verbose = 1;
break; break;
case 'o': case 'o':
config->output = optarg; config->output = optarg;
break; break;
case 'p':
config->prefix = optarg;
break;
case 's':
config->suffix = optarg;
break;
case 'b': case 'b':
sscanf(optarg, "%x", &config->size); sscanf(optarg, "%x", &config->size);
break; break;
// case 'n': case 'd':
// for (i = 0; i < 6; i++) { if (config->defsize >= DEF_MAX) {
// if (optarg[i] == 0) { printf("excess number of definitions\n");
// break; return 1;
// } }
// config->archname[i] = optarg[i]; defval = strchr(optarg, '=');
// } if (defval) {
// break; *defval = 0;
config->defs[config->defsize].name = optarg;
config->defs[config->defsize].value = defval + 1;
config->defsize++;
} else {
printf("definition value required:%s\n", optarg);
return 1;
}
break;
case 'h': case 'h':
printf("%s : Convert Intel HEX file (ihx) to binary file, ver. 2.0.0\n", getprogname()); printf("Hexameter: Convert Intel HEX file (ihx) to binary file, ver. 2.1.0\n");
printf("Copyright (c) 2003-2008 Takahide Matsutsuka <markn@markn.org>\n"); printf("Copyright (c) 2003-2008 Takahide Matsutsuka <markn@markn.org>\n");
printf("Usage: %s [options] <ihx> [<ihx>...]\n", argv[0]); printf("Usage: hexameter [options] <ihx|bin> [<ihx|bin>...]\n");
printf("Options:\n"); printf("Options:\n");
printf(" -v verbose output\n"); printf(" -v verbose output\n");
printf(" -o <output file name>\n"); printf(" -o <output file name>\n");
// printf(" -n <cassette file name> (for NEC PC series)\n"); printf(" -d <name>=<value> define property\n");
printf(" -p <prefix file>\n");
printf(" -s <suffix file>\n");
printf(" -b <output file size in hexadecimal bytes>\n"); printf(" -b <output file size in hexadecimal bytes>\n");
printf(" -h print this help\n"); printf(" -h show this help\n");
return 1; return 1;
default: default:
@ -150,7 +171,9 @@ static unsigned char analyzeOption(int argc, char **argv, struct Configuration *
return 0; return 0;
} }
static int isFileExists(const char *dir, const char *filename) { #if 0
static
int isFileExists(const char *dir, const char *filename) {
char path[MAX_PATH]; char path[MAX_PATH];
FILE *f; FILE *f;
@ -171,19 +194,25 @@ static int isFileExists(const char *dir, const char *filename) {
return 0; return 0;
} }
#endif
/**
* @return 1 if given filename has an extension of ".ihx"
*/
static
int isIhx(const char *filename) {
const char* pos = strcasestr(filename, IHXEXT);
if (pos && pos[strlen(IHXEXT)] == 0) {
return 1;
}
return 0;
}
static int checkExistence(struct Configuration *config) { static
int checkExistence(Configuration *config) {
int i; int i;
int r;
FILE *f; FILE *f;
fclose(f);
if (r = isFileExists(config->dir, config->prefix)) {
return r;
}
if (r = isFileExists(config->dir, config->suffix)) {
return r;
}
for (i = 0; i < config->length; i++) { for (i = 0; i < config->length; i++) {
f = fopen(config->files[i], "r"); f = fopen(config->files[i], "r");
if (!f) { if (!f) {
@ -201,7 +230,7 @@ static int checkExistence(struct Configuration *config) {
static static
int copy(FILE *out, const char* dir, const char* filename, unsigned char verbose) { int copy(FILE *out, const char* dir, const char* filename, unsigned char verbose) {
FILE *in; FILE *in;
char ch; int ch;
char path[MAX_PATH]; char path[MAX_PATH];
int bytes = 0; int bytes = 0;
if (!filename) { if (!filename) {
@ -213,31 +242,42 @@ int copy(FILE *out, const char* dir, const char* filename, unsigned char verbose
} else { } else {
strcpy(path, filename); strcpy(path, filename);
} }
if (verbose) {
printf("importing file: %s\n", path);
}
in = fopen(path, "rb"); in = fopen(path, "rb");
while ((ch = getc(in)) != EOF) { while ((ch = getc(in)) != EOF) {
putc(ch, out); putc(ch, out);
bytes++; bytes++;
} }
fclose(in);
if (verbose) {
printf("imported file: %s, size=%d\n", path, bytes);
}
return bytes; return bytes;
} }
static int output(struct Configuration *config) { static
int output(Configuration *config) {
FILE *out; FILE *out;
int i; int i;
// TODO: ARCH FILE NAME
if (!(out = fopen(config->output, "wb"))) { if (!(out = fopen(config->output, "wb"))) {
printf("cannot open output file:%s\n", config->output); printf("cannot open output file:%s\n", config->output);
return 1; return 1;
} }
config->written += copy(out, config->dir, config->prefix, config->verbose);
for (i = 0; i < config->length; i++) { for (i = 0; i < config->length; i++) {
config->written += ihx2bin(out, config->files[i], config->verbose); struct ConvertInfo info;
info.out = out;
info.filename = config->files[i];
info.verbose = config->verbose;
info.defsize = config->defsize;
info.defs = config->defs;
if (isIhx(config->files[i])) {
config->written += ihx2bin(&info);
} else {
config->written += copy(out, NULL, config->files[i], config->verbose);
}
} }
config->written += copy(out, config->dir, config->suffix, config->verbose);
if (config->size) { if (config->size) {
if (config->verbose) { if (config->verbose) {
@ -254,27 +294,14 @@ static int output(struct Configuration *config) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
struct Configuration config; Configuration config;
unsigned char r; unsigned char r;
memset(&config, 0, sizeof(struct Configuration)); memset(&config, 0, sizeof(Configuration));
#if __CYGWIN32__
char path[MAX_PATH];
GetModuleFileName(NULL, path, MAX_PATH);
int len = strlen(path);
while (len > 0) {
if (path[len] == '\\') {
path[len + 1] = 0;
break;
}
len--;
}
config.dir = path;
#endif
while (optind < argc) { while (optind < argc) {
if (r = analyzeOption(argc, argv, &config)) { r = analyzeOption(argc, argv, &config);
if (r) {
return r; return r;
} }
if (optind == argc) { if (optind == argc) {
@ -298,13 +325,15 @@ int main(int argc, char **argv) {
config.output = changeExt(config.files[0], "bin"); config.output = changeExt(config.files[0], "bin");
} }
if (r = checkExistence(&config)) { r = checkExistence(&config);
if (r) {
return r; return r;
} }
if (config.verbose) { if (config.verbose) {
printf("Generating file: %s\n", config.output); printf("Generating file: %s\n", config.output);
} }
if (r = output(&config)) { r = output(&config);
if (r) {
return r; return r;
} }

View file

@ -35,19 +35,41 @@
*/ */
/* /*
* Intel HEX format to PC-6001 CAS format conversion utility. * Intel HEX format (extended) to binary format conversion utility.
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "ihx2bin.h" #include "ihx2bin.h"
#define TYPE_DATA 0
#define TYPE_END 1
#define TYPE_STRING 2
#define TYPE_BYTE 3
#define TYPE_WORD 4
#define MEMORY_SIZE 0x10000
typedef struct {
unsigned int start;
unsigned int end;
unsigned char buffer[MEMORY_SIZE];
// current line
int type;
unsigned int address;
unsigned int length;
} Memory;
static
const char NAME_CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
/** /**
* Convert a character to a value. * Convert a character to a value.
* @param ch a character to convert * @param ch a character to convert
* @return integer value represents the given character * @return integer value represents the given character
*/ */
static int aton(const unsigned char ch) { static
int n; int aton(const unsigned char ch) {
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
return ch - '0'; return ch - '0';
} }
@ -66,19 +88,95 @@ static int aton(const unsigned char ch) {
* @param in file * @param in file
* @return -1 if EOF * @return -1 if EOF
*/ */
static int getByte(FILE *in) { static
int getByte(FILE *in) {
int ch1, ch2; int ch1, ch2;
ch1 = getc(in); if (feof(in)) {
if (ch1 == EOF) { printf("eof");
return -1; return -1;
} }
ch2 = getc(in); ch1 = fgetc(in);
if (ch2 == EOF) { if (feof(in)) {
printf("eof");
return -1; return -1;
} }
ch2 = fgetc(in);
return 16 * aton(ch1) + aton(ch2); return 16 * aton(ch1) + aton(ch2);
} }
/**
* @return non-zero if error
*/
static
void replace(FILE* in, struct ConvertInfo *info, Memory *memory) {
int i, j;
char name[DEF_NAMELEN];
int len = 0;
// read name
while (len < DEF_NAMELEN - 1) {
char ch = fgetc(in);
if (!strchr(NAME_CHARS, ch)) {
break;
}
name[len] = ch;
len++;
}
name[len] = 0;
for (i = 0; i < info->defsize; i++) {
if (!strcmp(name, info->defs[i].name)) {
int tmp;
char value[DEF_VALUELEN];
// replace!
switch (memory->type) {
case TYPE_STRING:
for (j = 0; j < memory->length; j++) {
memory->buffer[memory->address] = value[j] = info->defs[i].value[j];
memory->address++;
}
value[j] = 0;
if (info->verbose) {
printf("[%s]->[%s], ", name, value);
}
break;
case TYPE_BYTE:
tmp = 0;
for (j = 0; j < 2; j++) {
if (aton(info->defs[i].value[j])) {
tmp = tmp * 16 + aton(info->defs[i].value[j]);
}
}
memory->buffer[memory->address] = tmp;
if (info->verbose) {
printf("[%s]->[%02x], ", name, tmp);
}
break;
case TYPE_WORD:
tmp = 0;
for (j = 0; j < 2; j++) {
tmp = tmp * 16 + aton(info->defs[i].value[j]);
}
memory->buffer[memory->address + 1] = tmp;
tmp = 0;
for (j = 2; j < 4; j++) {
tmp = tmp * 16 + aton(info->defs[i].value[j]);
}
memory->buffer[memory->address] = tmp;
if (info->verbose) {
printf("[%s]->[%02x%02x], ", name,
memory->buffer[memory->address + 1],
memory->buffer[memory->address]);
}
break;
}
break;
}
}
}
/** /**
* Extract a 64kB memory map from given file. * Extract a 64kB memory map from given file.
* IHEX format is as follows: * IHEX format is as follows:
@ -86,6 +184,7 @@ static int getByte(FILE *in) {
* A_ : size of this chunk * A_ : size of this chunk
* B___: address (big endian) * B___: address (big endian)
* C_ : record type (00: notmal data, 01: end) * C_ : record type (00: notmal data, 01: end)
* extension: 02: char, 03: byte(hex), 04: word(hex, little-endian)
* D_....D_: data * D_....D_: data
* E_ : check sum * E_ : check sum
* :0DCCCF00673008D620D607D63013C937C904 * :0DCCCF00673008D620D607D63013C937C904
@ -95,68 +194,71 @@ static int getByte(FILE *in) {
* @param end pointer to end address * @param end pointer to end address
* @return 0 if noerror, otherwise if error * @return 0 if noerror, otherwise if error
*/ */
static int ihx2mem(const char *inFilename, unsigned char *buffer, unsigned int *start, unsigned int *end) { static
int ihx2mem(struct ConvertInfo *info, Memory *memory) {
FILE *in; FILE *in;
*start = 0xffff; memory->start = MEMORY_SIZE - 1;
*end = 0; memory->end = 0;
in = fopen(inFilename, "rb"); in = fopen(info->filename, "rb");
if (in == NULL) { if (in == NULL) {
printf("cannot open input file\n"); printf("cannot open input file\n");
return 1; return 1;
} }
while(1) { while(1) {
int ch;
int length;
unsigned int address;
int tmp; int tmp;
// skip checksum and cr/lf // skip checksum and cr/lf
while ((ch = getc(in)) != ':') { while (!feof(in)) {
if (ch == EOF) { if (fgetc(in) == ':') {
break; break;
} }
} }
if (ch == EOF) { if (feof(in)) {
break; break;
} }
// get length of this chunk // get length of this chunk
length = getByte(in); if ((memory->length = getByte(in)) < 0) {
if (length <= 0) {
// TODO: end of bytes, retrieve variables
break; break;
} }
// make an address // make an address
tmp = getByte(in); if ((tmp = getByte(in)) < 0) {
if (tmp < 0) {
break; break;
} }
address = tmp * 256; memory->address = tmp * 256;
tmp = getByte(in); if ((tmp = getByte(in)) < 0) {
if (tmp < 0) {
break; break;
} }
address += tmp; memory->address += tmp;
if (*start > address) {
*start = address;
}
if (*end < (address + length)) { // process record type
*end = address + length; if ((memory->type = getByte(in)) < 0) {
}
// ignore record type
if (getByte(in) < 0) {
break; break;
} }
while (length > 0) { if (memory->type != TYPE_END) {
buffer[address] = getByte(in); // modify start and end
address++; if (memory->start > memory->address) {
length--; memory->start = memory->address;
}
if (memory->end < (memory->address + memory->length)) {
memory->end = memory->address + memory->length;
}
}
if (memory->type == TYPE_DATA) {
while (memory->length > 0) {
memory->buffer[memory->address] = getByte(in);
memory->address++;
memory->length--;
}
} else if (memory->type == TYPE_STRING
|| memory->type == TYPE_BYTE
|| memory->type == TYPE_WORD) {
replace(in, info, memory);
} }
} }
@ -167,24 +269,28 @@ static int ihx2mem(const char *inFilename, unsigned char *buffer, unsigned int *
/** /**
* @return written size * @return written size
*/ */
int ihx2bin(FILE* dst, const char *src, unsigned char verbose) { int ihx2bin(struct ConvertInfo *info) {
unsigned int start, end; Memory memory;
unsigned char buffer[65536];
unsigned int i; unsigned int i;
memset(buffer, 0, 65536); memset(&memory, 0, sizeof(Memory));
if (ihx2mem(src, buffer, &start, &end)) { if (info->verbose) {
printf("cannot open input file: %s\n", src); printf("importing ihx: %s, ", info->filename);
}
if (ihx2mem(info, &memory)) {
printf("cannot open input file: %s\n", info->filename);
return 0; return 0;
} }
if (verbose) { if (info->verbose) {
printf("importing ihx : %s (%04x:%04x)\n", src, start, end); printf("(%04x:%04x)\n", memory.start, memory.end);
}
for (i = start; i < end; i++) {
putc(buffer[i], dst);
} }
return (end - start); for (i = memory.start; i < memory.end; i++) {
putc(memory.buffer[i], info->out);
}
return (memory.end - memory.start);
} }

View file

@ -27,7 +27,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: ihx2bin.h,v 1.1 2008/07/02 07:17:14 matsutsuka Exp $ * $Id: ihx2bin.h,v 1.2 2008/07/20 07:44:39 matsutsuka Exp $
* *
*/ */
@ -39,9 +39,27 @@
#ifndef __IHX2BIN_H__ #ifndef __IHX2BIN_H__
#define __IHX2BIN_H__ #define __IHX2BIN_H__
#define DEF_MAX 1024
#define DEF_NAMELEN 256
#define DEF_VALUELEN 256
struct ConvertDefinition {
char *name;
char *value;
};
struct ConvertInfo {
FILE* out;
char* filename;
unsigned char verbose;
unsigned int defsize;
struct ConvertDefinition *defs;
};
/* A default architecture-depend file name. */ /* A default architecture-depend file name. */
#define DEFAULT_ARCH_FILENAME "noname" #define DEFAULT_ARCH_FILENAME "noname"
int ihx2bin(FILE* dst, const char *src, unsigned char verbose); // int ihx2bin(FILE* dst, const char *src, unsigned char verbose);
int ihx2bin(struct ConvertInfo* info);
#endif /* __IHX2BIN_H__ */ #endif /* __IHX2BIN_H__ */

Binary file not shown.