From 1c7d0b339d578511be239c175ef2096e6e8aa6e2 Mon Sep 17 00:00:00 2001 From: Ian C Date: Sat, 21 Aug 2004 01:15:19 +0000 Subject: Added new files --- Makefile | 36 ++++++++++--- int2tap.1 | 9 +++- int2tap.c | 132 ++++++++++++++++++++++++++++++++++++++++++++-- intel.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ intel.h | 54 +++++++++++++++++++ tap.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tap.h | 50 ++++++++++++++++++ 7 files changed, 616 insertions(+), 14 deletions(-) create mode 100644 intel.c create mode 100644 intel.h create mode 100644 tap.c create mode 100644 tap.h diff --git a/Makefile b/Makefile index 8a02f77..d4b4cb3 100644 --- a/Makefile +++ b/Makefile @@ -18,21 +18,43 @@ # # ------------------------------------------------------------------------- # -# $Id: Makefile,v 1.1.1.1 2004-08-20 01:14:42 ianc Exp $ +# $Id: Makefile,v 1.2 2004-08-21 01:15:19 ianc Exp $ # # CFLAGS assumes that gcc is being used - simply change as required # -CFLAGS = -g -Wall -Werror $(DEBUG) +CFLAGS = -g -Wall -Werror TARGET = int2tap +SOURCE = int2tap.c \ + intel.c \ + tap.c -$(TARGET): $(TARGET).c - $(CC) $(CFLAGS) -o $(TARGET) $(TARGET).c +OBJECTS = int2tap.o \ + intel.o \ + tap.o -$(TARGET).txt: $(TARGET).1 - nroff -man $(TARGET).1 | sed 's/.//g' > $(TARGET).txt +$(TARGET): $(OBJECTS) + $(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS) clean: - rm -f $(TARGET) core + rm -f $(TARGET) $(OBJECTS) core + +depend: + make clean + makedepend -- $(CFLAGS) $(DEBUG) -- $(SOURCE) + if test -e Makefile ; then rm -f Makefile.bak ; fi + +# DO NOT DELETE THIS LINE -- make depend depends on it + +int2tap.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +int2tap.o: /usr/include/machine/ansi.h /usr/include/stdio.h +int2tap.o: /usr/include/string.h /usr/include/stdarg.h /usr/include/time.h +int2tap.o: /usr/include/sys/_posix.h /usr/include/errno.h +intel.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +intel.o: /usr/include/machine/ansi.h /usr/include/string.h +intel.o: /usr/include/stdio.h intel.h +tap.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +tap.o: /usr/include/machine/ansi.h /usr/include/string.h /usr/include/stdio.h +tap.o: tap.h diff --git a/int2tap.1 b/int2tap.1 index e8cb4a6..12953b3 100644 --- a/int2tap.1 +++ b/int2tap.1 @@ -1,4 +1,4 @@ -.TH int2tap 1 "20 August 2004" +.TH int2tap 1 .SH NAME hex2tap \- Converts an Intel format segment dump to a Spectrum emulator TAP file. @@ -20,6 +20,12 @@ TAP file. takes one or more Intel format segment files \- as produced by an assembler like .B tpasm(1) \- and produces a Spectrum compatible tape file (TAP file). +.P +The tape file will also optionally include a BASIC loader (see OPTIONS). +This loader will do a CLEAR to the execution address (see +.B -a +in OPTIONS), and then load in the binary files in the same order they were on +the command line. .SH OPTIONS .B int2tap accepts these switches @@ -29,7 +35,6 @@ Just produce the binary file. By default .B int2tap will generate a TAP file with two files in - a BASIC loader and then the code itself. This switch disables the generation of the BASIC loader portion. -disabled if this switch is provided (see USAGE). .TP .B \-s By default diff --git a/int2tap.c b/int2tap.c index 68902a2..b2fba26 100644 --- a/int2tap.c +++ b/int2tap.c @@ -20,6 +20,8 @@ ------------------------------------------------------------------------- + $Name$ + */ static const char id[]="$Id$"; @@ -30,8 +32,11 @@ static const char id[]="$Id$"; #include #include +#include "intel.h" +#include "tap.h" + -/* ---------------------------------------- MACROS +/* ---------------------------------------- GLOBALS */ #undef TRUE #undef FALSE @@ -39,19 +44,136 @@ static const char id[]="$Id$"; #define TRUE 1 #define FALSE 0 - -/* ---------------------------------------- TYPES -*/ +const char *progname; -/* ---------------------------------------- PROTOS +/* ---------------------------------------- PRIVATE UTILS */ +static void Usage(void) +{ + fprintf(stderr,"%s: usage %s [ -b ] [ -s ] [ -a address ] " + "output-file input-file ... \n",progname,progname); +} /* ---------------------------------------- MAIN */ int main(int argc, char *argv[]) { + unsigned char mem[0x10000]; + IntelInfo *info; + char *outname; + unsigned exec_addr; + int bin_only; + int split; + int addr_defined; + int base; + int no; + int f; + int done; + + /* Set program name + */ + if ((progname=strrchr(argv[0],'/'))) + { + progname++; + } + else + { + progname=argv[0]; + } + + /* Set defaults and parse args + */ + addr_defined=FALSE; + bin_only=FALSE; + split=FALSE; + + done=FALSE; + f=1; + + while(fargc-2) + { + Usage(); + } + + addr_defined=TRUE; + + exec_addr=(unsigned)strtoul(argv[++f],NULL,0); + + break; + + default: + Usage(); + break; + } + + f++; + } + } + + if (base>=argc-1) + { + Usage(); + } + + outname=argv[base++]; + + no=argc-base; + + if (!(info=malloc(sizeof *info * no))) + { + fprintf(stderr,"%s: malloc failed\n",progname); + } + + /* Process Intel files + */ + for(f=0;f +#include +#include + +#include "intel.h" + +static const char header_id[]=I2T_INTEL_H; + +extern const char *progname; + + +/* ---------------------------------------- CONSTANTS +*/ +#undef TRUE +#undef FALSE + +#define TRUE 1 +#define FALSE 0 + + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +static const unsigned ToHex(char c) +{ + if (c>='0' && c<='9') + { + return c-'0'; + } + + if (c>='A' && c<='F') + { + return c-'A'+10; + } + + if (c>='a' && c<='f') + { + return c-'a'+10; + } + + return 0; +} + + + +/* ---------------------------------------- INTERFACES +*/ +int IntelLoad(const char *filename, + unsigned char mem [0x1000], + IntelInfo *info) +{ + FILE *fp; + char buff[1024]; + int done; + int addr_read; + int ret; + + if (!(fp=fopen(filename,"r"))) + { + fprintf(stderr,"%s: Failed to open %s\n",progname,filename); + return FALSE; + } + + addr_read=FALSE; + info->low=0xffff; + info->high=0x0000; + + done=FALSE; + ret=FALSE; + + while(!done) + { + if (!fgets(buff,sizeof buff,fp)) + { + fprintf(stderr,"%s: Missing EOF record in %s\n",progname,filename); + done=TRUE; + } + + if (!done && buff[0]!=':') + { + fprintf(stderr,"%s: Invalid Intel HEX file %s\n",progname,filename); + done=TRUE; + } + + if (!done && buff[8]=='1') + { + done=TRUE; + ret=TRUE; + } + + if (!done && (buff[8]=='2' || buff[8]=='3')) + { + fprintf(stderr,"%s: Extended address in Intel HEX file %s\n", + progname,filename); + done=TRUE; + } + + if (!done) + { + unsigned addr; + unsigned len; + unsigned f; + + len=ToHex(buff[1])<<4|ToHex(buff[2]); + + addr=ToHex(buff[3])<<12|ToHex(buff[4])<<8| + ToHex(buff[5])<<4|ToHex(buff[6]); + + if (!addr_read) + { + info->addr=addr; + addr_read=TRUE; + } + + for(f=0;flow) + { + info->low=addr; + } + + if (addr>info->high) + { + info->high=addr; + } + + b=ToHex(buff[f*2+9])<<4|ToHex(buff[f*2+10]); + mem[addr++]=b; + + if (addr==0) + { + fprintf(stderr,"%s: Intel HEX file %s has " + "wrapped from 0xffff to 0x0000\n", + progname,filename); + done=TRUE; + } + } + } + } + + if (info->low!=0xffff) + { + info->len=(info->high-info->low)+1; + } + + fclose(fp); + + return ret; +} + + +/* END OF FILE */ diff --git a/intel.h b/intel.h new file mode 100644 index 0000000..b34ef37 --- /dev/null +++ b/intel.h @@ -0,0 +1,54 @@ +/* + + int2tap - Convert an Intel segment file to a loadable Spectrum tape file + + Copyright (C) 2004 Ian Cowburn (ianc@noddybox.demon.co.uk) + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + $Id$ + +*/ + +#ifndef I2T_INTEL_H +#define I2T_INTEL_H "$Id$" + +/* ---------------------------------------- TYPES +*/ +typedef struct +{ + unsigned addr; + unsigned low; + unsigned high; + unsigned len; +} IntelInfo; + +/* ---------------------------------------- INTERFACES +*/ + +/* Loads an Intel segment file. Returns FALSE for failure. + If it works, info.addr is filled with the address of the first byte + written from the file and info.low and info.high hold the lowest and + highest address written to respectively. +*/ +int IntelLoad(const char *filename, + unsigned char mem [0x1000], + IntelInfo *info); + +#endif + +/* END OF FILE */ diff --git a/tap.c b/tap.c new file mode 100644 index 0000000..0c9b3c7 --- /dev/null +++ b/tap.c @@ -0,0 +1,171 @@ +/* + + int2tap - Convert an Intel segment file to a loadable Spectrum tape file + + Copyright (C) 2004 Ian Cowburn (ianc@noddybox.demon.co.uk) + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + +*/ +static const char id[]="$Id$"; + +#include +#include +#include + +#include "tap.h" + +static const char header_id[]=I2T_TAP_H; + + +/* ---------------------------------------- CONSTANTS +*/ +#undef TRUE +#undef FALSE + +#define TRUE 1 +#define FALSE 0 + + +/* ---------------------------------------- TYPES +*/ + + +/* ---------------------------------------- GLOBALS +*/ +extern const char *progname; + +static FILE *fp; +static int file_no; + + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +unsigned char TapWord(unsigned w, unsigned char chk) +{ + putc(w&0xff,fp); + chk^=w&0xff; + putc(w>>8,fp); + chk^=w>>8; + return chk; +} + +unsigned char TapByte(unsigned char c, unsigned char chk) +{ + putc(c,fp); + chk^=c; + return chk; +} + +unsigned char TapString(char *p, int len, unsigned char chk) +{ + while(len--) + { + chk=TapByte(*p++,chk); + } + + return chk; +} + +unsigned char TapStream(const unsigned char p[0x10000], + unsigned addr, unsigned len, unsigned char chk) +{ + while(len--) + { + chk=TapByte(p[addr],chk); + addr=(addr+1)&0xffff; + } + + return chk; +} + +/* ---------------------------------------- INTERFACES +*/ + +int TapOpen(const char *filename) +{ + file_no=0; + + if (!(fp=fopen(filename,"wb"))) + { + fprintf(stderr,"%s: Failed to create %s\n",progname,filename); + } + + return fp!=NULL; +} + + +void TapWrite(const unsigned char mem[0x1000], + unsigned addr, unsigned len, int is_code) +{ + char name[11]={0}; + unsigned char chk; + + sprintf(name,"%10.10d",file_no); + file_no=(file_no+1)%10000; + + /* Output file header + */ + chk=TapWord(19,chk); + chk=TapByte(0,chk); + + if (is_code) + { + chk=TapByte(3,chk); + } + else + { + chk=TapByte(3,chk); + } + + chk=TapString(name,10,chk); + chk=TapWord(len,chk); + + if (is_code) + { + chk=TapWord(addr,chk); + chk=TapWord(32768,chk); + } + else + { + chk=TapWord(0,chk); + chk=TapWord(0,chk); + } + + TapByte(chk,0); + + /* Output file data + */ + chk=0; + + chk=TapWord(len+2,chk); + chk=TapStream(mem,addr,len,chk); + TapByte(chk,0); +} + + +void TapClose(void) +{ + if (fp) + { + fclose(fp); + fp=NULL; + } +} + + +/* END OF FILE */ diff --git a/tap.h b/tap.h new file mode 100644 index 0000000..38be2c6 --- /dev/null +++ b/tap.h @@ -0,0 +1,50 @@ +/* + + int2tap - Convert an Intel segment file to a loadable Spectrum tape file + + Copyright (C) 2004 Ian Cowburn (ianc@noddybox.demon.co.uk) + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + $Id$ + +*/ + +#ifndef I2T_TAP_H +#define I2T_TAP_H "$Id$" + +/* ---------------------------------------- INTERFACES +*/ + +/* Opens the TAP file for writing. Returns FALSE on failure. +*/ +int TapOpen(const char *filename); + +/* Write a block of memory to the TAP file. +*/ +void TapWrite(const unsigned char mem[0x1000], + unsigned addr, + unsigned len, + int is_code); + +/* Close the TAP file. +*/ +void TapClose(void); + +#endif + +/* END OF FILE */ -- cgit v1.2.3